1. 引言

1.1 项目背景

IEC 61850 是电力自动化领域的重要标准,其中 CID(Configured IED Description)文件描述了智能电子设备(IED)的配置信息,包括数据集、报告控制块、数据实例等。在工程实践中,往往需要从 CSV 表格导入配置数据,自动生成符合标准的 CID 文件,以提高配置效率和准确性。

1.2 目的与目标

本程序旨在提供一个图形化工具,通过解析用户定义的 CSV 文件,结合 IEC 61850 数据类型模板(DataTypeTemplates.xml),生成完整的 CID 文件。主要目标包括:

  • 支持多逻辑设备(LDevice)配置,LDevice 实例名取自 CSV。
  • 自动为每个数据集生成报告控制块(仅当数据集包含 ST/MX 类型数据)。
  • 根据 CSV 中的描述(desc)填充 DOI 的 desc 属性和 dU 的值。
  • 支持 CSV 中指定数据属性(DAI)的 sAddr 属性。
  • 对 CSV 中出现的所有 DO/DA 路径进行模板存在性校验,确保配置与模板一致。
  • 提供详细的调试日志窗口,方便用户排查问题。

2. 系统概述

2.1 功能简介

程序通过 PyQt6 构建图形界面,主要流程如下:

  1. 用户选择 CSV 文件(可自动检测编码)和数据类型模板 XML 文件。
  2. 点击“Parse CSV”按钮,预览 CSV 数据。
  3. 点击“Generate CID”按钮,程序解析 CSV、验证模板、生成 CID 文件,并弹出保存对话框。
  4. 底部的调试窗口实时显示解析过程中的警告、错误和统计信息。

2.2 技术栈

  • 编程语言:Python 3
  • GUI 框架:PyQt6
  • 数据处理:csv 模块(标准库)、xml.etree.ElementTree(标准库)
  • 编码检测:尝试常用编码(utf-8, gbk, gb2312, ansi, cp1252)

3. 功能需求

3.1 核心功能

  • CSV 解析:读取 CSV 文件,支持多种编码,自动检测。
  • 数据类型模板加载:解析 DataTypeTemplates.xml,提取 LNodeType、DOType、DAType、EnumType。
  • 逻辑节点(LN)实例化:根据 CSV 中出现的 LNType 自动创建 LN 元素,并为每个 LN 下的 DO 生成 DOI 及其子 DAI。
  • 数据集生成:根据 CSV 中 Type=Dataset 的行,为每个数据集名称收集 FCDA 列表,生成 DataSet 元素。
  • 报告控制块生成:仅当数据集所有 FCDA 的 FC 为 ST 或 MX 时生成 ReportControl,并根据 FC 类型决定缓冲属性(ST→缓冲,MX→非缓冲,混合→缓冲并告警)。报告属性包括 intgPd="30000", rptID="NULL", bufTime="100" 等,TrgOps 和 OptFields 按示例固定。
  • DOI 描述映射:将 CSV 中的 Desc 列设置为对应 DOI 的 desc 属性,并用于填充 dU 的值。
  • sAddr 属性:将 CSV 中的 sAddr 列设置为对应 DAI 的 sAddr 属性(支持复合 DA 路径,如 mag.f)。
  • 多 LDevice:根据 CSV 中的 LDName 列创建多个 LDevice,LDevice 顺序与 CSV 中首次出现顺序一致,每个 LDevice 下拥有独立的 LLN0。
  • prefix 支持:CSV 中的 prefix 列应用到 FCDA 和 LN 元素。
  • 模板存在性校验:对 CSV 中每一行(包括 Dataset 和 Control)的 DO 和 DA 路径,递归检查是否在模板中存在,若不存在则报错并终止生成。
  • LN 重复性校验:同一 LDevice 下不允许出现相同的 (prefix, lnClass, lnInst) 组合。
  • 数据集 FCDA 数量限制:单个数据集的 FCDA 数量超过 256 时报错。
  • FCDA 简化:生成的 FCDA 中不包含 daName 属性。

3.2 高级特性

  • 自动为 LLN0 创建默认实例(若 CSV 中未定义)。
  • 报告按 LDevice 分组,每个 LDevice 内先放置所有 DataSet,再放置所有 ReportControl。
  • 支持排除特定 DO(如 SV)和特定 DAI(如 subEna, subVal 等取代相关 DAI)的实例化。
  • 跳过 fc=CF 的 DAI 实例化。

4. 系统架构

4.1 总体架构

程序采用 MVC 风格的单窗口架构,由以下几部分组成:

  • 视图层:MainWindow 类(PyQt6),包含文件选择、按钮、表格、日志窗口。
  • 控制层:MainWindow 的事件处理方法(parse_csv, generate_cid),负责协调数据流。
  • 模型层:DataTypeResolver 类(模板解析与查询)、CSV 解析函数、CID 生成函数(generate_cid)。

4.2 模块划分

  • CSV 解析模块parse_csv 函数,自动检测编码,返回列表字典。
  • 模板解析模块DataTypeResolver 类,解析 XML 并构建类型字典,提供类型查询、默认值获取、路径验证等功能。
  • 数据收集与验证模块:在 MainWindow.generate_cid 中,分多步收集原始数据、验证 LN 重复性、验证模板路径、构建最终数据结构。
  • CID 生成模块generate_cid 函数,接收处理好的数据结构,构造 SCL 树并写入文件。
  • 日志模块:通过 log_message 回调,将信息输出到调试窗口。

5. 模块设计

5.1 DataTypeResolver 类

  • 属性
    • lnode_typesdo_typesda_typesenum_types:字典,ID 到对应 XML 元素的映射。
  • 方法
    • _parse():遍历模板根节点,填充各字典。
    • get_ln_type(type_id)get_do_type(type_id)get_da_type(type_id):返回对应元素,若不存在则记录警告。
    • get_enum_default(enum_type_id):返回枚举类型中 ord 最小的枚举值文本。
    • verify_do_da_path(ln_type_id, do_name, da_full_path):递归验证给定 LN 类型下是否存在指定 DO 的 DA 路径。利用 _find_da_in_do_type 和 _find_bda_in_da_type 实现。
    • generate_doi_for_ln(...):核心方法,为指定 LN 生成所有 DOI。遍历 LNodeType 的 DO 元素,为每个 DO 创建 DOI,调用 _generate_dai_for_do 递归生成 DAI,并在控制 DO 时强制注入 ctlModel/sboTimeout。
    • _generate_dai_for_do_generate_bda_for_da_type_create_dai:递归处理 DOType 和 DAType,生成 DAI 或 SDI,并根据模板默认值、CSV 描述、sAddr、控制标志等设置值。

5.2 数据收集与验证模块

位于 MainWindow.generate_cid 中,分为多个步骤:

  1. 收集原始数据:遍历所有 CSV 行(仅 Dataset 和 Control),提取:
    • raw_ln_info:键 (ld, prefix, ln_inst, ln_type) → True,用于后续 LN 实例收集。
    • raw_fcda_list:仅 Dataset 行,存储数据集信息。
    • raw_do_desc:键 (ld, prefix, ln_inst, ln_type, do_name) → desc,用于 DOI 描述。
    • raw_dai_saddr:键 (ld, prefix, ln_inst, ln_type, do_name, da_name) → sAddr。
    • validation_items:存储 (ld, prefix, ln_inst, ln_type, do_name, da_name) 用于模板验证。
  2. LN 解析与重复性校验
    • 遍历 raw_ln_info,通过 dt_resolver.get_ln_type 获取 lnClass,构建 ln_candidates 列表。
    • 检查重复 LN(同一 LD 下 (prefix, ln_class, ln_inst) 是否重复),若重复则报错退出。
    • 构建最终 ln_instances 字典:键 (ld, prefix, ln_class, ln_inst) → ln_type。
  3. 模板存在性校验
    • 遍历 validation_items,利用 dt_resolver.verify_do_da_path 验证路径,失败则记录并最终报错。
  4. 构建 do_desc_map、dai_saddr_map:将原始键中的 ln_type 替换为 ln_class。
  5. 构建 control_do_by_ln:记录每个 LN 下的控制 DO 名称集合。
  6. 构建 datasets:将 raw_fcda_list 转换为以数据集名称为键的字典,每个 fcda 包含 ldInst, prefix, lnClass, lnInst, doName, daName, fc。

5.3 CID 生成模块(generate_cid 函数)

  1. 创建 SCL 根元素,添加固定的 Header、Communication 块(模板化内容)。
  2. 添加 IED 元素,并在其中添加固定的 Services 块。
  3. 创建 AccessPoint(name="S1")和 Server,并添加 Authentication。
  4. 多 LDevice 处理
    • 收集所有出现的 LDevice 名称,按首次出现顺序构建列表。
    • 为每个 LDevice 创建 <LDevice> 元素,inst 属性直接取 LDName。
  5. 创建 LN 元素
    • 先遍历所有 LDevice,为每个 LDevice 创建其下的 LLN0(若 CSV 中未定义,则自动创建默认 LLN0)。
    • 再创建其他 LN,确保 LLN0 位于 LDevice 子节点最前面。
  6. 数据集与报告分组
    • 将数据集按 LDevice 分组(ld_datasets)。
    • 对每个 LDevice,先遍历所有数据集生成 <DataSet> 元素,再遍历所有数据集生成 <ReportControl> 元素,实现所有数据集在前、所有报告在后的顺序。
  7. 报告生成逻辑
    • 检查数据集所有 FCDA 的 FC 集合,若不为 {'ST'}、{'MX'} 或 {'ST','MX'} 则跳过。
    • 根据 FC 集合确定缓冲属性、entryID 值。
    • 设置报告属性:name(brcb/urcb+数据集名首字母大写)、datSetintgPd="30000"rptID="NULL"confRev="1"bufferedbufTime="100"
    • 添加 TrgOps 和 OptFields 子元素(按示例固定)。
  8. DOI 生成
    • 遍历所有 LN 元素,调用 dt_resolver.generate_doi_for_ln,传入对应 LN 的 do_desc_map、dai_saddr_map 和控制 DO 集合。
    • 在 generate_doi_for_ln 内部,处理完模板中的 DAI 后,若 DO 在控制集合中,则强制添加/覆盖 ctlModel 和 sboTimeout。
  9. 添加数据类型模板(深拷贝后附加)。
  10. 写入文件,使用 ET.indent 美化输出。

5.4 GUI 界面(MainWindow 类)

  • 布局:垂直布局,包含文件选择、IED 名称输入、解析按钮、表格、生成按钮、调试窗口。
  • 表格:用于预览 CSV 数据,自动调整列宽。
  • 调试窗口:只读 QTextEdit,通过 log_message 方法添加带时间戳的日志,自动滚动到底部。
  • 按钮事件:
    • browse_file:选择 CSV 文件。
    • browse_dt_file:选择 XML 模板文件,加载并初始化 DataTypeResolver。
    • parse_csv:解析 CSV 并填充表格。
    • generate_cid:执行上述数据收集、验证、生成流程,若出错则弹出消息框并记录日志。

6. 关键算法与数据结构

6.1 CSV 编码检测

尝试一系列常用编码(utf-8, gbk, gb2312, ansi, cp1252),直至成功读取。若全部失败,抛出异常。

6.2 模板路径验证算法

verify_do_da_path 采用递归下降方式:

  • 首先在 LNodeType 中查找指定 DO,获取其 DOType ID。
  • 然后在 DOType 中按路径段逐步查找:若当前段对应 SDO,则进入其引用的 DOType;若对应 DA 且 bType="Struct",则进入其引用的 DAType;若对应 DA 且为叶子,则返回成功;若对应 BDA,类似处理。
  • 若任何一步查找失败,返回 False 并记录详细日志。

6.3 递归生成 DOI/DAI

generate_doi_for_ln 遍历 LNodeType 的 DO,为每个 DO 创建 DOI,然后调用 _generate_dai_for_do 处理 DOType 的 DA 和 SDO。_generate_dai_for_do 递归遍历 DA 和 SDO,对于结构体类型,创建 SDI 并进入子结构。此过程中,会利用传入的 dai_saddr_map(键为 (do_name, full_path))为叶子 DAI 设置 sAddr 属性,并根据是否控制 DO 和当前 DA 名称,决定是否覆盖值为固定值。

6.4 多 LDevice 顺序保持

使用 OrderedDict 和列表记录首次出现的 LDevice 名称,确保生成顺序与 CSV 中首次出现顺序一致。

6.5 数据集与报告顺序控制

在 generate_cid 中,对每个 LDevice 先循环生成所有 DataSet,再循环生成所有 ReportControl,不混合。

6.6 控制 DO 特殊 DAI 注入

在 generate_doi_for_ln 中,处理完模板中的 DAI 后,通过 doi.find 检查是否已存在 ctlModel 和 sboTimeout,若不存在则创建新的 DAI,并设置固定值的 <Val> 子元素。这保证了即使模板中未定义这些 DAI,最终 CID 中也会出现。

6.7 数据结构设计

  • ln_instances{(ld, prefix, lnClass, lnInst): ln_type},用于快速查找 LN 类型。
  • do_desc_map{(ld, prefix, lnClass, lnInst, doName): desc},用于设置 DOI 的 desc。
  • dai_saddr_map{(ld, prefix, lnClass, lnInst, doName, fullDaPath): sAddr},用于设置 DAI 的 sAddr。
  • control_do_by_ln{(ld, prefix, lnClass, lnInst): set(doName)},用于识别控制 DO。
  • datasets{ds_name: {"desc": ds_desc, "fcda": [fcda_dict]}},其中 fcda_dict 包含 ldInst, prefix, lnClass, lnInst, doName, daName, fc。

7. 使用说明

7.1 环境准备

  • 安装 Python 3.6+。
  • 安装 PyQt6:pip install PyQt6
  • 准备 CSV 文件和数据类型模板 XML 文件。

7.2 CSV 格式要求

  • 必须包含以下列(大小写敏感):
    • Type:取值 Dataset 或 Control
    • Name:数据集名称(仅 Dataset 行需要)。
    • LDName:逻辑设备实例名(如 LD0LD1)。
    • prefix:LN 前缀(可为空)。
    • LNInst:LN 实例号(可为空,表示 0)。
    • LNType:逻辑节点类型 ID,必须与模板中的 LNodeType id 匹配。
    • DOName:数据对象名称。
    • DAName:数据属性完整路径(如 stValmag.f)。
    • FC:功能约束(如 STMXCO)。
    • Desc:描述(可选,用于 DOI 的 desc 和 dU 的值)。
    • sAddr:sAddr 属性值(可选)。
  • 示例:

csv

Type,Name,LDName,prefix,LNInst,LNType,DOName,DAName,FC,Desc,sAddr
Dataset,dsAlm,LD0,,1,SQTECH_GGIO_ALM,Alm1,stVal,ST,遥信1,yx004
Control,,LD0,,1,SQTECH_GGIO_SPC,SPCSO1,Oper.ctlVal,CO,遥控1,yk000

7.3 数据类型模板要求

  • 必须是有效的 XML 文件,包含 <DataTypeTemplates> 根元素(可位于 <SCL> 内或作为根)。
  • 模板中必须包含所有 CSV 中引用的 LNType、DOType、DAType、EnumType。
  • 每个 LNodeType 必须有 lnClass 属性。

7.4 操作步骤

  1. 运行程序:python csv_to_cid.py
  2. 点击“Browse CSV”选择 CSV 文件。
  3. 点击“Browse XML”选择数据类型模板文件。
  4. 输入 IED 名称(默认 IED1)。
  5. 点击“Parse CSV”预览数据。
  6. 点击“Generate CID”,选择保存路径。
  7. 查看调试窗口中的日志,确认无错误后,CID 文件生成成功。

下载地址:sqtech_2018 (sqtech_2018) - Gitee.com

Logo

AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。

更多推荐