diff --git a/DeviceCommand/Devices/IOBoardGroup.cs b/DeviceCommand/Devices/IOBoardGroup.cs index 393e7cb..963e77d 100644 --- a/DeviceCommand/Devices/IOBoardGroup.cs +++ b/DeviceCommand/Devices/IOBoardGroup.cs @@ -11,14 +11,26 @@ using System.ComponentModel; namespace DeviceCommand.Devices { /// - /// 系统控制功能类型枚举 (中文) + /// 系统控制功能类型枚举 (根据三工位 ACP接线图 更新) /// public enum 功能动作 : byte { - 单相充电, - 抛负载, - 短路测试, - 蜂鸣器报警 + 产品充电三相, + 产品放电三相, + KL30通断, + KL15通断, + 电子锁60欧电阻, + 温度检测1K欧电阻, + CC信号串1K欧电阻, + CP信号串1K欧电阻, + CC信号串680欧电阻, + CC信号串220欧电阻, + CC信号串100欧电阻, + CC信号空载, + 蜂鸣器报警, + 抛负载通断, // (接线图中标注于 Y14, KM8) + 短路测试HV, // (接线图中标注于 Y15, KM9) + 短路测试LV // (接线图中标注于 Y16, KM10) } /// @@ -26,7 +38,7 @@ namespace DeviceCommand.Devices /// public struct IoPortInfo { - public int ModuleIndex { get; set; } // IO板卡/模块序号 (1 或 2) + public int ModuleIndex { get; set; } // IO板卡/模块序号 (1、2 或 3) public ushort Address { get; set; } // 转换为 Modbus 的线圈相对偏移地址 (Y1->0, Y2->1) public IoPortInfo(int moduleIndex, ushort address) @@ -39,79 +51,89 @@ namespace DeviceCommand.Devices [ACPCommand] public class IOBoardGroup { - // 声明底层的 2 个 IO 板卡实例 + // 声明底层的 3 个 IO 板卡实例(对应三工位系统) public IOBoard Board1 { get; private set; } public IOBoard Board2 { get; private set; } + public IOBoard Board3 { get; private set; } private readonly byte _slaveAddress = 1; // 默认 Modbus 从站号为 1 - // 核心:严格对齐图片数据的双层嵌套配置字典 (2个模块,1-8台架) + // 核心:根据 ACP硬件接线图 严格对齐的数据字典 (3个模块独立对应1-3工位) private static readonly Dictionary> IoMapping = new Dictionary>() { + // 1# 工位 -> IO继电器模块 1# { 1, new Dictionary<功能动作, IoPortInfo> { - { 功能动作.单相充电, new IoPortInfo(1, 5) }, // Y6 -> 5 - { 功能动作.抛负载, new IoPortInfo(1, 0) }, // Y1 -> 0 - { 功能动作.短路测试, new IoPortInfo(1, 1) }, // Y2 -> 1 - { 功能动作.蜂鸣器报警, new IoPortInfo(2, 15) } // Y9 -> 8 + { 功能动作.产品充电三相, new IoPortInfo(1, 0) }, // Y1 -> 0 (KM2) + { 功能动作.产品放电三相, new IoPortInfo(1, 1) }, // Y2 -> 1 (KM3) + { 功能动作.KL30通断, new IoPortInfo(1, 2) }, // Y3 -> 2 + { 功能动作.KL15通断, new IoPortInfo(1, 3) }, // Y4 -> 3 + { 功能动作.电子锁60欧电阻, new IoPortInfo(1, 4) }, // Y5 -> 4 + { 功能动作.温度检测1K欧电阻, new IoPortInfo(1, 5) }, // Y6 -> 5 + { 功能动作.CC信号串1K欧电阻, new IoPortInfo(1, 6) }, // Y7 -> 6 + { 功能动作.CP信号串1K欧电阻, new IoPortInfo(1, 7) }, // Y8 -> 7 + { 功能动作.CC信号串680欧电阻, new IoPortInfo(1, 8) }, // Y9 -> 8 + { 功能动作.CC信号串220欧电阻, new IoPortInfo(1, 9) }, // Y10 -> 9 + { 功能动作.CC信号串100欧电阻, new IoPortInfo(1, 10) }, // Y11 -> 10 + { 功能动作.CC信号空载, new IoPortInfo(1, 11) }, // Y12 -> 11 + { 功能动作.蜂鸣器报警, new IoPortInfo(1, 12) }, // Y13 -> 12 + { 功能动作.抛负载通断, new IoPortInfo(3, 13) }, // Y14 -> 13 (KM8) + { 功能动作.短路测试HV, new IoPortInfo(3, 14) }, // Y15 -> 14 (KM9) + { 功能动作.短路测试LV, new IoPortInfo(3, 15) } // Y16 -> 15 (KM10) }}, + // 2# 工位 -> IO继电器模块 2# { 2, new Dictionary<功能动作, IoPortInfo> { - { 功能动作.单相充电, new IoPortInfo(1, 6) }, // Y7 -> 6 - { 功能动作.抛负载, new IoPortInfo(1, 2) }, // Y3 -> 2 - { 功能动作.短路测试, new IoPortInfo(1, 1) }, // Y2 -> 1 - { 功能动作.蜂鸣器报警, new IoPortInfo(2, 14) } // Y10 -> 9 + { 功能动作.产品充电三相, new IoPortInfo(2, 0) }, // Y1 -> 0 (KM4) + { 功能动作.产品放电三相, new IoPortInfo(2, 1) }, // Y2 -> 1 (KM5) + { 功能动作.KL30通断, new IoPortInfo(2, 2) }, // Y3 -> 2 + { 功能动作.KL15通断, new IoPortInfo(2, 3) }, // Y4 -> 3 + { 功能动作.电子锁60欧电阻, new IoPortInfo(2, 4) }, // Y5 -> 4 + { 功能动作.温度检测1K欧电阻, new IoPortInfo(2, 5) }, // Y6 -> 5 + { 功能动作.CC信号串1K欧电阻, new IoPortInfo(2, 6) }, // Y7 -> 6 + { 功能动作.CP信号串1K欧电阻, new IoPortInfo(2, 7) }, // Y8 -> 7 + { 功能动作.CC信号串680欧电阻, new IoPortInfo(2, 8) }, // Y9 -> 8 + { 功能动作.CC信号串220欧电阻, new IoPortInfo(2, 9) }, // Y10 -> 9 + { 功能动作.CC信号串100欧电阻, new IoPortInfo(2, 10) }, // Y11 -> 10 + { 功能动作.CC信号空载, new IoPortInfo(2, 11) }, // Y12 -> 11 + { 功能动作.蜂鸣器报警, new IoPortInfo(2, 12) }, // Y13 -> 12 + { 功能动作.抛负载通断, new IoPortInfo(3, 13) }, // Y14 -> 13 (KM8) + { 功能动作.短路测试HV, new IoPortInfo(3, 14) }, // Y15 -> 14 (KM9) + { 功能动作.短路测试LV, new IoPortInfo(3, 15) } // Y16 -> 15 (KM10) }}, + // 3# 工位 -> IO继电器模块 3# (包含额外的抛负载及短路测试控制) { 3, new Dictionary<功能动作, IoPortInfo> { - { 功能动作.单相充电, new IoPortInfo(1, 7) }, // Y8 -> 7 - { 功能动作.抛负载, new IoPortInfo(1, 3) }, // Y4 -> 3 - { 功能动作.短路测试, new IoPortInfo(1, 1) }, // Y2 -> 1 - { 功能动作.蜂鸣器报警, new IoPortInfo(2, 13) } // Y11 -> 10 - }}, - { 4, new Dictionary<功能动作, IoPortInfo> { - { 功能动作.单相充电, new IoPortInfo(1, 8) }, // Y9 -> 8 - { 功能动作.抛负载, new IoPortInfo(1, 4) }, // Y5 -> 4 - { 功能动作.短路测试, new IoPortInfo(1, 1) }, // Y2 -> 1 - { 功能动作.蜂鸣器报警, new IoPortInfo(2, 12) } // Y12 -> 11 - }}, - { 5, new Dictionary<功能动作, IoPortInfo> { - { 功能动作.单相充电, new IoPortInfo(2, 4) }, // Y5 -> 4 - { 功能动作.抛负载, new IoPortInfo(2, 0) }, // Y1 -> 0 - { 功能动作.短路测试, new IoPortInfo(1, 1) }, // Y2 -> 1 - { 功能动作.蜂鸣器报警, new IoPortInfo(2, 11) } // Y13 -> 12 - }}, - { 6, new Dictionary<功能动作, IoPortInfo> { - { 功能动作.单相充电, new IoPortInfo(2, 5) }, // Y6 -> 5 - { 功能动作.抛负载, new IoPortInfo(2, 1) }, // Y2 -> 1 - { 功能动作.短路测试, new IoPortInfo(1, 1) }, // Y2 -> 1 - { 功能动作.蜂鸣器报警, new IoPortInfo(2, 10) } // Y14 -> 13 - }}, - { 7, new Dictionary<功能动作, IoPortInfo> { - { 功能动作.单相充电, new IoPortInfo(2, 6) }, // Y7 -> 6 - { 功能动作.抛负载, new IoPortInfo(2, 2) }, // Y3 -> 2 - { 功能动作.短路测试, new IoPortInfo(1, 1) }, // Y2 -> 1 - { 功能动作.蜂鸣器报警, new IoPortInfo(2, 9) } // Y15 -> 14 - }}, - { 8, new Dictionary<功能动作, IoPortInfo> { - { 功能动作.单相充电, new IoPortInfo(2, 7) }, // Y8 -> 7 - { 功能动作.抛负载, new IoPortInfo(2, 3) }, // Y4 -> 3 - { 功能动作.短路测试, new IoPortInfo(1, 1) }, // Y2 -> 1 - { 功能动作.蜂鸣器报警, new IoPortInfo(2, 8) } // Y16 -> 15 + { 功能动作.产品充电三相, new IoPortInfo(3, 0) }, // Y1 -> 0 (KM6) + { 功能动作.产品放电三相, new IoPortInfo(3, 1) }, // Y2 -> 1 (KM7) + { 功能动作.KL30通断, new IoPortInfo(3, 2) }, // Y3 -> 2 + { 功能动作.KL15通断, new IoPortInfo(3, 3) }, // Y4 -> 3 + { 功能动作.电子锁60欧电阻, new IoPortInfo(3, 4) }, // Y5 -> 4 + { 功能动作.温度检测1K欧电阻, new IoPortInfo(3, 5) }, // Y6 -> 5 + { 功能动作.CC信号串1K欧电阻, new IoPortInfo(3, 6) }, // Y7 -> 6 + { 功能动作.CP信号串1K欧电阻, new IoPortInfo(3, 7) }, // Y8 -> 7 + { 功能动作.CC信号串680欧电阻, new IoPortInfo(3, 8) }, // Y9 -> 8 + { 功能动作.CC信号串220欧电阻, new IoPortInfo(3, 9) }, // Y10 -> 9 + { 功能动作.CC信号串100欧电阻, new IoPortInfo(3, 10) }, // Y11 -> 10 + { 功能动作.CC信号空载, new IoPortInfo(3, 11) }, // Y12 -> 11 + { 功能动作.蜂鸣器报警, new IoPortInfo(3, 12) }, // Y13 -> 12 + { 功能动作.抛负载通断, new IoPortInfo(3, 13) }, // Y14 -> 13 (KM8) + { 功能动作.短路测试HV, new IoPortInfo(3, 14) }, // Y15 -> 14 (KM9) + { 功能动作.短路测试LV, new IoPortInfo(3, 15) } // Y16 -> 15 (KM10) }} }; - public IOBoardGroup(IOBoard board1, IOBoard board2) + // 修改构造函数以支持 3 个板块 + public IOBoardGroup(IOBoard board1, IOBoard board2, IOBoard board3) { Board1 = board1 ?? throw new ArgumentNullException(nameof(board1), "IOBoard Board1 实例不能为空。"); Board2 = board2 ?? throw new ArgumentNullException(nameof(board2), "IOBoard Board2 实例不能为空。"); + Board3 = board3 ?? throw new ArgumentNullException(nameof(board3), "IOBoard Board3 实例不能为空。"); } - - /// /// 执行指定台架的功能动作控制(带高低电平开关及底层安全互锁) /// - /// 台架/工位序号 (1 - 8) - /// 控制功能类型 (单相充电, 抛负载, 短路测试, 蜂鸣器报警) + /// 台架/工位序号 (1 - 3) + /// 控制功能类型 /// 开关状态 (true: 开启吸合, false: 关闭断开) /// 异步取消令牌 public async Task 执行台架动作Async(int 台架序号, 功能动作 动作, bool 开关状态, CancellationToken 取消令牌 = default) @@ -119,21 +141,25 @@ namespace DeviceCommand.Devices // 1. 根据传入的台架序号和动作检索字典映射关系 if (!IoMapping.TryGetValue(台架序号, out var 动作字典) || !动作字典.TryGetValue(动作, out var io信息)) { - throw new ArgumentException($"未找到台架 [{台架序号}] 对应功能 [{动作}] 的 IO 点位映射配置。"); + throw new ArgumentException($"未找到台架 [{台架序号}] 对应功能 [{动作}] 的 IO 点位映射配置。请注意抛负载及短路测试仅存在于 3# 工位。"); } - // 2. 软件防错高危互锁逻辑 + // 2. 软件防错高危互锁逻辑:防止同时执行充电和放电 if (开关状态) { - if (动作 == 功能动作.单相充电) + if (动作 == 功能动作.产品充电三相) { - var 短路点位 = IoMapping[台架序号][功能动作.短路测试]; - await GetBoardInstance(短路点位.ModuleIndex).写输出开关(_slaveAddress, 短路点位.Address, false); + if (IoMapping[台架序号].TryGetValue(功能动作.产品放电三相, out var 放电点位)) + { + await GetBoardInstance(放电点位.ModuleIndex).写输出开关(_slaveAddress, 放电点位.Address, false); + } } - else if (动作 == 功能动作.短路测试) + else if (动作 == 功能动作.产品放电三相) { - var 充电点位 = IoMapping[台架序号][功能动作.单相充电]; - await GetBoardInstance(充电点位.ModuleIndex).写输出开关(_slaveAddress, 充电点位.Address, false); + if (IoMapping[台架序号].TryGetValue(功能动作.产品充电三相, out var 充电点位)) + { + await GetBoardInstance(充电点位.ModuleIndex).写输出开关(_slaveAddress, 充电点位.Address, false); + } } } @@ -151,7 +177,8 @@ namespace DeviceCommand.Devices { 1 => Board1, 2 => Board2, - _ => throw new ArgumentOutOfRangeException(nameof(moduleIndex), "非法的板卡序号,系统仅支持 1# 和 2# 模块。") + 3 => Board3, + _ => throw new ArgumentOutOfRangeException(nameof(moduleIndex), "非法的板卡序号,系统仅支持 1#、2# 和 3# 模块。") }; return board ?? throw new InvalidOperationException($"IO板卡模块 [{moduleIndex}#] 尚未完成初始化,无法建立总线通信。"); diff --git a/UIShare/GlobalVariable/DeviceManager.cs b/UIShare/GlobalVariable/DeviceManager.cs index 6db7b4d..b328120 100644 --- a/UIShare/GlobalVariable/DeviceManager.cs +++ b/UIShare/GlobalVariable/DeviceManager.cs @@ -214,15 +214,15 @@ namespace UIShare.GlobalVariable // IOGroup 初始化:从已实例化的设备中取出前两个 IOBoard 实例组建 IOBoardGroup try { - var ioBoards = DeviceMap.Values.OfType().Take(2).ToList(); - if (ioBoards.Count == 2) + var ioBoards = DeviceMap.Values.OfType().Take(3).ToList(); + if (ioBoards.Count == 3) { - IOGroup = new IOBoardGroup(ioBoards[0], ioBoards[1]); - LoggerHelper.Info($"IOBoardGroup 已初始化,Board1={ioBoards[0].GetType().Name}, Board2={ioBoards[1].GetType().Name}。"); + IOGroup = new IOBoardGroup(ioBoards[0], ioBoards[1], ioBoards[2]); + LoggerHelper.Info($"IOBoardGroup 已初始化,Board1={ioBoards[0].GetType().Name}, Board2={ioBoards[1].GetType().Name}, Board3={ioBoards[2].GetType().Name}。"); } else { - LoggerHelper.Warn($"IOBoardGroup 初始化跳过:需要 2 个 IOBoard 实例,当前仅找到 {ioBoards.Count} 个。"); + LoggerHelper.Warn($"IOBoardGroup 初始化跳过:需要 3 个 IOBoard 实例,当前仅找到 {ioBoards.Count} 个。"); } } catch (Exception ex)