using System.Globalization; using System.IO; using System.Text; using System.Windows; using System.Windows.Controls; using System.Windows.Controls.Primitives; using System.Windows.Data; using System.Windows.Media; using System.Windows.Shapes; using System.Windows.Threading; using ErvDashboard.Api; using ErvDashboard.Model; using ErvProtocol; using Microsoft.Win32; namespace ErvDashboard { public partial class MainWindow : Window { const int BaudRate = 115200; readonly DashboardState _state = new(); readonly IErvApi _api = new SerialErvApi(); readonly DispatcherTimer _demoTimer; int _demoTick; bool _commActive; bool _ledDragging; // LED 슬라이더 thumb 드래그 중 (드래그 중엔 전송 보류 → 완료 시 1회) bool _suppressLed; // STATUS 동기 적용 중 LedDim→슬라이더 갱신으로 인한 ValueChanged 전송 차단 readonly Dictionary _lastLed = new(); // roomId→마지막 송신/수신 LED. 동일값 재전송(에코) 차단 static readonly Brush Accent = Brush2("#3B82F6"); static readonly Brush AccentSoftBr = Brush2("#E7F0FF"); static readonly Brush CardBgBr = Brush2("#FFFFFF"); static readonly Brush CardBorderBr = Brush2("#E3E7EF"); static readonly Brush TextPrimaryBr = Brush2("#1F2733"); static readonly Brush GoodBr = Brush2("#22C55E"); static readonly Brush BadBr = Brush2("#EF4444"); static Brush Brush2(string hex) => (Brush)new BrushConverter().ConvertFromString(hex)!; // 운전모드 버튼 정의 static readonly (string tag, string label, RunMode mode)[] ModeDefs = { ("Vent", "환기", RunMode.Vent), ("Auto", "자동", RunMode.Auto), ("AirClean", "공청", RunMode.AirClean), ("Bypass", "바이패스", RunMode.Bypass), }; readonly List