220 lines
8.7 KiB
C#
220 lines
8.7 KiB
C#
using System;
|
||
using System.Configuration;
|
||
using XP.Common.Logging.Interfaces;
|
||
using XP.Hardware.Plc.Exceptions;
|
||
|
||
namespace XP.Hardware.PLC.Configs
|
||
{
|
||
/// <summary>
|
||
/// PLC 配置加载器(读取 App.config)| PLC Configuration Loader (reads from App.config)
|
||
/// </summary>
|
||
public class ConfigLoader
|
||
{
|
||
private readonly ILoggerService _logger;
|
||
|
||
/// <summary>
|
||
/// 构造函数 | Constructor
|
||
/// </summary>
|
||
/// <param name="logger">日志服务 | Logger service</param>
|
||
public ConfigLoader(ILoggerService logger)
|
||
{
|
||
_logger = logger.ForModule("ConfigLoader");
|
||
}
|
||
|
||
/// <summary>
|
||
/// 从 App.config 加载 PLC 配置 | Load PLC configuration from App.config
|
||
/// </summary>
|
||
/// <param name="prefix">配置前缀,默认为 "Plc" | Configuration prefix, default is "Plc"</param>
|
||
/// <returns>PLC 配置对象 | PLC configuration object</returns>
|
||
public PlcConfig LoadPlcConfig(string prefix = "Plc")
|
||
{
|
||
try
|
||
{
|
||
_logger.Info($"开始从 App.config 加载 PLC 配置,前缀: {prefix}");
|
||
|
||
var config = new PlcConfig();
|
||
|
||
// 读取 IP 地址 | Read IP address
|
||
var ipAddress = ConfigurationManager.AppSettings[$"{prefix}:IpAddress"];
|
||
if (!string.IsNullOrEmpty(ipAddress))
|
||
{
|
||
config.IpAddress = ipAddress;
|
||
}
|
||
|
||
// 读取端口号 | Read port
|
||
var port = ConfigurationManager.AppSettings[$"{prefix}:Port"];
|
||
if (int.TryParse(port, out var portValue))
|
||
{
|
||
config.Port = portValue;
|
||
}
|
||
|
||
// 读取 Rack | Read Rack
|
||
var rack = ConfigurationManager.AppSettings[$"{prefix}:Rack"];
|
||
if (short.TryParse(rack, out var rackValue))
|
||
{
|
||
config.Rack = rackValue;
|
||
}
|
||
|
||
// 读取 Slot | Read Slot
|
||
var slot = ConfigurationManager.AppSettings[$"{prefix}:Slot"];
|
||
if (short.TryParse(slot, out var slotValue))
|
||
{
|
||
config.Slot = slotValue;
|
||
}
|
||
|
||
// 读取 PLC 类型 | Read PLC type
|
||
var plcType = ConfigurationManager.AppSettings[$"{prefix}:PlcType"];
|
||
if (!string.IsNullOrEmpty(plcType) && Enum.TryParse<PlcType>(plcType, true, out var plcTypeValue))
|
||
{
|
||
config.PlcType = plcTypeValue;
|
||
}
|
||
else if (!string.IsNullOrEmpty(plcType))
|
||
{
|
||
_logger.Warn($"无效的 PLC 类型: {plcType},使用默认值: {config.PlcType}");
|
||
}
|
||
|
||
// 读取数据块配置 | Read data block configuration
|
||
var readDbBlock = ConfigurationManager.AppSettings[$"{prefix}:ReadDbBlock"];
|
||
if (!string.IsNullOrEmpty(readDbBlock))
|
||
{
|
||
config.ReadDbBlock = readDbBlock;
|
||
}
|
||
|
||
var readStartAddress = ConfigurationManager.AppSettings[$"{prefix}:ReadStartAddress"];
|
||
if (int.TryParse(readStartAddress, out var readStartValue))
|
||
{
|
||
config.ReadStartAddress = readStartValue;
|
||
}
|
||
|
||
var readLength = ConfigurationManager.AppSettings[$"{prefix}:ReadLength"];
|
||
if (int.TryParse(readLength, out var readLengthValue))
|
||
{
|
||
config.ReadLength = readLengthValue;
|
||
}
|
||
|
||
// 读取批量读取周期 | Read bulk read interval
|
||
var bulkReadInterval = ConfigurationManager.AppSettings[$"{prefix}:BulkReadIntervalMs"];
|
||
if (int.TryParse(bulkReadInterval, out var bulkReadIntervalValue))
|
||
{
|
||
config.BulkReadIntervalMs = bulkReadIntervalValue;
|
||
}
|
||
|
||
// 读取超时配置 | Read timeout configuration
|
||
var connectTimeout = ConfigurationManager.AppSettings[$"{prefix}:ConnectTimeoutMs"];
|
||
if (int.TryParse(connectTimeout, out var connectTimeoutValue))
|
||
{
|
||
config.ConnectTimeoutMs = connectTimeoutValue;
|
||
}
|
||
|
||
var readTimeout = ConfigurationManager.AppSettings[$"{prefix}:ReadTimeoutMs"];
|
||
if (int.TryParse(readTimeout, out var readTimeoutValue))
|
||
{
|
||
config.ReadTimeoutMs = readTimeoutValue;
|
||
}
|
||
|
||
var writeTimeout = ConfigurationManager.AppSettings[$"{prefix}:WriteTimeoutMs"];
|
||
if (int.TryParse(writeTimeout, out var writeTimeoutValue))
|
||
{
|
||
config.WriteTimeoutMs = writeTimeoutValue;
|
||
}
|
||
|
||
// 读取重连配置 | Read reconnection configuration
|
||
var bReConnect = ConfigurationManager.AppSettings[$"{prefix}:bReConnect"];
|
||
if (bool.TryParse(bReConnect, out var bReConnectValue))
|
||
{
|
||
config.bReConnect = bReConnectValue;
|
||
}
|
||
|
||
// 验证配置参数 | Validate configuration parameters
|
||
ValidateConfig(config);
|
||
|
||
_logger.Info($"成功加载 PLC 配置: {config.IpAddress}:{config.Port}, Rack={config.Rack}, Slot={config.Slot}, 型号={config.PlcType}");
|
||
return config;
|
||
}
|
||
catch (PlcException)
|
||
{
|
||
// PlcException 直接向上抛出 | Re-throw PlcException
|
||
throw;
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
_logger.Error(ex, $"加载 PLC 配置失败: {ex.Message}");
|
||
throw new PlcException("配置加载失败", ex);
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 验证配置参数 | Validate configuration parameters
|
||
/// </summary>
|
||
/// <param name="config">PLC 配置对象 | PLC configuration object</param>
|
||
private void ValidateConfig(PlcConfig config)
|
||
{
|
||
// 验证 IP 地址不为空 | Validate IP address is not empty
|
||
if (string.IsNullOrWhiteSpace(config.IpAddress))
|
||
{
|
||
throw new PlcException("PLC IP 地址不能为空");
|
||
}
|
||
|
||
// 验证端口号范围 (1-65535) | Validate port range (1-65535)
|
||
if (config.Port < 1 || config.Port > 65535)
|
||
{
|
||
throw new PlcException($"PLC 端口号无效: {config.Port},有效范围: 1-65535");
|
||
}
|
||
|
||
// 验证 Rack 范围 (0-7) | Validate Rack range (0-7)
|
||
if (config.Rack < 0 || config.Rack > 7)
|
||
{
|
||
throw new PlcException($"Rack 参数无效: {config.Rack},有效范围: 0-7");
|
||
}
|
||
|
||
// 验证 Slot 范围 (0-31) | Validate Slot range (0-31)
|
||
if (config.Slot < 0 || config.Slot > 31)
|
||
{
|
||
throw new PlcException($"Slot 参数无效: {config.Slot},有效范围: 0-31");
|
||
}
|
||
|
||
// 验证超时时间大于 0 | Validate timeout is greater than 0
|
||
if (config.ConnectTimeoutMs <= 0)
|
||
{
|
||
throw new PlcException($"连接超时时间无效: {config.ConnectTimeoutMs},必须大于 0");
|
||
}
|
||
|
||
if (config.ReadTimeoutMs <= 0)
|
||
{
|
||
throw new PlcException($"读取超时时间无效: {config.ReadTimeoutMs},必须大于 0");
|
||
}
|
||
|
||
if (config.WriteTimeoutMs <= 0)
|
||
{
|
||
throw new PlcException($"写入超时时间无效: {config.WriteTimeoutMs},必须大于 0");
|
||
}
|
||
|
||
// 验证数据块配置,缺失时使用默认值 | Validate data block configuration, use default if missing
|
||
if (string.IsNullOrWhiteSpace(config.ReadDbBlock))
|
||
{
|
||
_logger.Warn("ReadDbBlock 未配置,使用默认值: DB1");
|
||
config.ReadDbBlock = "DB1";
|
||
}
|
||
|
||
if (config.ReadLength <= 0)
|
||
{
|
||
_logger.Warn($"ReadLength 无效: {config.ReadLength},使用默认值: 100");
|
||
config.ReadLength = 100;
|
||
}
|
||
|
||
if (config.ReadStartAddress < 0)
|
||
{
|
||
_logger.Warn($"ReadStartAddress 无效: {config.ReadStartAddress},使用默认值: 0");
|
||
config.ReadStartAddress = 0;
|
||
}
|
||
|
||
// 验证批量读取周期 | Validate bulk read interval
|
||
if (config.BulkReadIntervalMs <= 0)
|
||
{
|
||
_logger.Warn($"BulkReadIntervalMs 无效: {config.BulkReadIntervalMs},使用默认值: 100");
|
||
config.BulkReadIntervalMs = 100;
|
||
}
|
||
}
|
||
}
|
||
}
|