@@ -11,14 +11,26 @@ using System.ComponentModel;
namespace DeviceCommand.Devices
{
/// <summary>
/// 系统控制功能类型枚举 (中文 )
/// 系统控制功能类型枚举 (根据三工位 ACP接线图 更新 )
/// </summary>
public enum 功 能 动 作 : byte
{
单 相 充 电 ,
抛 负 载 ,
短 路 测 试 ,
蜂 鸣 器 报 警
产 品 充 电 三 相 ,
产 品 放 电 三 相 ,
KL30通断 ,
KL15通断 ,
电 子 锁 60 欧 电 阻 ,
温 度 检 测 1 K欧电阻 ,
CC信号串1K欧电阻 ,
CP信号串1K欧电阻 ,
CC信号串680欧电阻 ,
CC信号串220欧电阻 ,
CC信号串100欧电阻 ,
CC信号空载 ,
蜂 鸣 器 报 警 ,
抛 负 载 通 断 , // (接线图中标注于 Y14, KM8)
短 路 测 试 HV , // (接线图中标注于 Y15, KM9)
短 路 测 试 LV // (接线图中标注于 Y16, KM10)
}
/// <summary>
@@ -26,7 +38,7 @@ namespace DeviceCommand.Devices
/// </summary>
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 < int , Dictionary < 功 能 动 作 , IoPortInfo > > IoMapping
= new Dictionary < int , Dictionary < 功 能 动 作 , IoPortInfo > > ( )
{
// 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
{ 功 能 动 作 . 温 度 检 测 1 K欧电阻 , 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
{ 功 能 动 作 . 温 度 检 测 1 K欧电阻 , 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 , 1 3) } // 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
{ 功 能 动 作 . 温 度 检 测 1 K欧电阻 , 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 实例不能为空。" ) ;
}
/// <summary>
/// 执行指定台架的功能动作控制(带高低电平开关及底层安全互锁)
/// </summary>
/// <param name="台架序号">台架/工位序号 (1 - 8 )</param>
/// <param name="动作">控制功能类型 (单相充电, 抛负载, 短路测试, 蜂鸣器报警) </param>
/// <param name="台架序号">台架/工位序号 (1 - 3 )</param>
/// <param name="动作">控制功能类型</param>
/// <param name="开关状态">开关状态 (true: 开启吸合, false: 关闭断开)</param>
/// <param name="取消令牌">异步取消令牌</param>
public async Task 执 行 台 架 动 作 Async ( int 台 架 序 号 , 功 能 动 作 动 作 , bool 开 关 状 态 , CancellationToken 取 消 令 牌 = default )
@@ -119,23 +141,27 @@ 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 ( 动 作 = = 功 能 动 作 . 产 品 放 电 三 相 )
{
if ( IoMapping [ 台 架 序 号 ] . TryGetValue ( 功 能 动 作 . 产 品 充 电 三 相 , out var 充 电 点 位 ) )
{
var 充 电 点 位 = IoMapping [ 台 架 序 号 ] [ 功 能 动 作 . 单 相 充 电 ] ;
await GetBoardInstance ( 充 电 点 位 . ModuleIndex ) . 写 输 出 开 关 ( _slaveAddress , 充 电 点 位 . Address , false ) ;
}
}
}
// 3. 动态获取目标板卡实例并直接驱动开关端口
IOBoard 目 标 板 卡 = GetBoardInstance ( io信息 . ModuleIndex ) ;
@@ -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}#] 尚未完成初始化,无法建立总线通信。" ) ;