using System.IO; namespace Housing.Services; public sealed class StartSignalSettings { public bool Enabled { get; set; } public string Connection { get; set; } = "Ni6501"; public string PhysicalChannel { get; set; } = "Dev1/port0/line0"; public string ActiveState { get; set; } = "High"; public string Host { get; set; } = string.Empty; public int Port { get; set; } = 5000; public string ReadCommand { get; set; } = string.Empty; public string ActiveResponse { get; set; } = "START,1,ON"; public string ResponseMatch { get; set; } = "Contains"; public string Terminator { get; set; } = "CRLF"; public int ReadTimeoutMilliseconds { get; set; } = 1000; public int PollIntervalMilliseconds { get; set; } = 50; public int TimeoutMilliseconds { get; set; } = 30000; public int PostSignalDelayMilliseconds { get; set; } = 2000; public bool RequireInactiveBeforeStart { get; set; } = true; public bool IsActive(bool lineValue) { return string.Equals(ActiveState, "Low", StringComparison.OrdinalIgnoreCase) ? !lineValue : lineValue; } public static StartSignalSettings Load(string filePath) { if (!File.Exists(filePath)) { throw new FileNotFoundException("Hardware.ini 파일을 찾을 수 없습니다.", filePath); } var values = IniFile.LoadSection(filePath, "StartSignal"); return new StartSignalSettings { Enabled = GetBool(values, "Enabled", false), Connection = GetString(values, "Connection", "Ni6501"), PhysicalChannel = GetString(values, "PhysicalChannel", "Dev1/port0/line0"), ActiveState = GetString(values, "ActiveState", "High"), Host = GetString(values, "Host", string.Empty), Port = GetInt(values, "Port", 5000), ReadCommand = GetString(values, "ReadCommand", string.Empty), ActiveResponse = GetString(values, "ActiveResponse", "START,1,ON"), ResponseMatch = GetString(values, "ResponseMatch", "Contains"), Terminator = GetString(values, "Terminator", "CRLF"), ReadTimeoutMilliseconds = Math.Max(100, GetInt(values, "ReadTimeoutMilliseconds", 1000)), PollIntervalMilliseconds = Math.Max(10, GetInt(values, "PollIntervalMilliseconds", 50)), TimeoutMilliseconds = Math.Max(0, GetInt(values, "TimeoutMilliseconds", 30000)), PostSignalDelayMilliseconds = Math.Max(0, GetInt(values, "PostSignalDelayMilliseconds", 2000)), RequireInactiveBeforeStart = GetBool(values, "RequireInactiveBeforeStart", true) }; } public string[] GetActiveResponses() { return ActiveResponse .Split(',', ';') .Select(value => value.Trim()) .Where(value => !string.IsNullOrWhiteSpace(value)) .ToArray(); } public string GetTerminator() { return Terminator.Trim().ToUpperInvariant() switch { "CRLF" => "\r\n", "CR" => "\r", "LF" => "\n", "NONE" or "EMPTY" => string.Empty, _ => Terminator }; } public bool IsActive(string response) { if (string.IsNullOrWhiteSpace(response)) { return false; } var activeResponses = GetActiveResponses(); if (activeResponses.Length == 0) { return false; } return string.Equals(ResponseMatch, "Equals", StringComparison.OrdinalIgnoreCase) ? activeResponses.Any(value => string.Equals(response.Trim(), value, StringComparison.OrdinalIgnoreCase)) : activeResponses.Any(value => response.Contains(value, StringComparison.OrdinalIgnoreCase)); } private static string GetString(Dictionary values, string key, string defaultValue) { return values.TryGetValue(key, out var value) && !string.IsNullOrWhiteSpace(value) ? value.Trim() : defaultValue; } private static int GetInt(Dictionary values, string key, int defaultValue) { return values.TryGetValue(key, out var value) && int.TryParse(value, out var result) ? result : defaultValue; } private static bool GetBool(Dictionary values, string key, bool defaultValue) { if (!values.TryGetValue(key, out var value) || string.IsNullOrWhiteSpace(value)) { return defaultValue; } return value.Trim().ToUpperInvariant() switch { "1" or "TRUE" or "YES" or "ON" => true, "0" or "FALSE" or "NO" or "OFF" => false, _ => defaultValue }; } }