# CSV to IEC61850 CID 转换器 **Repository Path**: sqtech_2018/csv_to_cid ## Basic Information - **Project Name**: CSV to IEC61850 CID 转换器 - **Description**: IEC 61850 是电力自动化领域的重要标准,其中 CID(Configured IED Description)文件描述了智能电子设备(IED)的配置信息,包括数据集、报告控制块、数据实例等。在工程实践中,往往需要从 CSV 表格导入配置数据,自动生成符合标准的 CID 文件,以提高配置效率和准确性。 - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 1 - **Forks**: 0 - **Created**: 2026-03-19 - **Last Updated**: 2026-03-20 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # CSV to IEC61850 CID 转换器 ![输入图片说明](image.png) ## 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_types`, `do_types`, `da_types`, `enum_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 创建 `` 元素,`inst` 属性直接取 LDName。 5. **创建 LN 元素**: - 先遍历所有 LDevice,为每个 LDevice 创建其下的 LLN0(若 CSV 中未定义,则自动创建默认 LLN0)。 - 再创建其他 LN,确保 LLN0 位于 LDevice 子节点最前面。 6. **数据集与报告分组**: - 将数据集按 LDevice 分组(`ld_datasets`)。 - 对每个 LDevice,先遍历所有数据集生成 `` 元素,再遍历所有数据集生成 `` 元素,实现所有数据集在前、所有报告在后的顺序。 7. **报告生成逻辑**: - 检查数据集所有 FCDA 的 FC 集合,若不为 {'ST'}、{'MX'} 或 {'ST','MX'} 则跳过。 - 根据 FC 集合确定缓冲属性、entryID 值。 - 设置报告属性:`name`(brcb/urcb+数据集名首字母大写)、`datSet`、`intgPd="30000"`、`rptID="NULL"`、`confRev="1"`、`buffered`、`bufTime="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,并设置固定值的 `` 子元素。这保证了即使模板中未定义这些 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`:逻辑设备实例名(如 `LD0`, `LD1`)。 - `prefix`:LN 前缀(可为空)。 - `LNInst`:LN 实例号(可为空,表示 0)。 - `LNType`:逻辑节点类型 ID,必须与模板中的 LNodeType id 匹配。 - `DOName`:数据对象名称。 - `DAName`:数据属性完整路径(如 `stVal`, `mag.f`)。 - `FC`:功能约束(如 `ST`, `MX`, `CO`)。 - `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 文件,包含 `` 根元素(可位于 `` 内或作为根)。 - 模板中必须包含所有 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 文件生成成功。 email: sqtech_2018@163.com QQ : 3521967540