chore: HERV 통합 저장소 초기 커밋

- 펌웨어(program), C# 대시보드(TestProgram), 시뮬레이터(Simulator),
  프로토콜/문서(Protocol, doc) 전체를 단일 저장소로 통합
- program 폴더의 별도 git 저장소를 제거하고 통합 저장소에 흡수
- 빌드 산출물(program/build, bin/obj, *.o/.elf/.bin/.hex 등) .gitignore 처리
- 사내 Synology NAS Git 원격 연결 예정

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-06-15 21:44:23 +09:00
commit 5a96a696b1
265 changed files with 76458 additions and 0 deletions
@@ -0,0 +1,389 @@
<Window x:Class="ERVSimulator.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:ERVSimulator"
Title="ERV 시뮬레이터 - ERV Simulator"
Width="1500" Height="880"
MinWidth="1400" MinHeight="800"
Background="{StaticResource PrimaryBgBrush}"
WindowStartupLocation="CenterScreen">
<Window.Resources>
<local:BoolToOpenCloseConverter x:Key="BoolOC"/>
<local:BoolToBrushConverter x:Key="BoolBrush"/>
<local:ColorTagToBrushConverter x:Key="TagBrush"/>
</Window.Resources>
<Grid Margin="14">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/> <!-- 0: Title/Connection -->
<RowDefinition Height="Auto"/> <!-- 1: Power + RunMode + Errors -->
<RowDefinition Height="Auto"/> <!-- 2: BodyDampers -->
<RowDefinition Height="Auto"/> <!-- 3: 자동운전 상태 -->
<RowDefinition Height="*"/> <!-- 4: Log -->
</Grid.RowDefinitions>
<!-- Row 0: 타이틀 + 통신 설정 -->
<Border Grid.Row="0" Style="{StaticResource SectionCard}">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<StackPanel Grid.Column="0" Orientation="Horizontal" VerticalAlignment="Center">
<TextBlock Text="ERV 시뮬레이터" FontSize="20" FontWeight="Bold"
Foreground="{StaticResource AccentCyanBrush}" Margin="0,0,14,0"/>
</StackPanel>
<StackPanel Grid.Column="1" VerticalAlignment="Center" Margin="0,0,24,0">
<TextBlock Text="만든이 : 전경선" Foreground="{StaticResource TextSecondaryBrush}" FontSize="10"/>
<TextBlock Text="수정일 : 2026.05.22" Foreground="{StaticResource TextSecondaryBrush}" FontSize="10"/>
</StackPanel>
<StackPanel Grid.Column="3" Orientation="Vertical">
<!-- 통신 포트 카드 1x4 (각 포트 = 2줄: 상단 라벨·포트·통신속도 / 하단 연결·해제·상태) -->
<UniformGrid Columns="4">
<!-- RoomCon -->
<Border Style="{StaticResource InnerCard}" Margin="0,0,6,0" Padding="8,6">
<StackPanel>
<StackPanel Orientation="Horizontal" Margin="0,0,0,5">
<TextBlock Text="RoomCon" Foreground="{StaticResource TextPrimaryBrush}" VerticalAlignment="Center"
Width="62" FontSize="11" FontWeight="SemiBold"/>
<ComboBox x:Name="RoomConPortCombo" Width="92" Style="{StaticResource ModernComboBox}" Margin="0,0,6,0"/>
<TextBlock Text="9600 8N1" Foreground="{StaticResource TextSecondaryBrush}" VerticalAlignment="Center" FontSize="11"/>
</StackPanel>
<StackPanel Orientation="Horizontal">
<Button x:Name="RoomConConnectBtn" Content="연결" Style="{StaticResource ModernButton}" Click="RoomConConnect_Click" Padding="12,5" Margin="0,0,4,0"/>
<Button x:Name="RoomConDisconnectBtn" Content="해제" Style="{StaticResource ModernButton}" Click="RoomConDisconnect_Click" Padding="12,5"
Background="{StaticResource AccentRedBrush}"/>
<Ellipse x:Name="RoomConStatus" Width="10" Height="10" Margin="10,0,4,0" Fill="#F7768E" VerticalAlignment="Center"/>
<TextBlock x:Name="RoomConStatusText" Text="미연결" Foreground="{StaticResource TextSecondaryBrush}" VerticalAlignment="Center" FontSize="11"/>
</StackPanel>
</StackPanel>
</Border>
<!-- HomeNet -->
<Border Style="{StaticResource InnerCard}" Margin="0,0,6,0" Padding="8,6">
<StackPanel>
<StackPanel Orientation="Horizontal" Margin="0,0,0,5">
<TextBlock Text="HomeNet" Foreground="{StaticResource TextPrimaryBrush}" VerticalAlignment="Center"
Width="62" FontSize="11" FontWeight="SemiBold"/>
<ComboBox x:Name="HomeNetPortCombo" Width="92" Style="{StaticResource ModernComboBox}" Margin="0,0,6,0"/>
<ComboBox x:Name="HomeNetBaudCombo" Width="76" Style="{StaticResource ModernComboBox}" SelectedIndex="5">
<ComboBoxItem Content="4800"/>
<ComboBoxItem Content="9600"/>
<ComboBoxItem Content="19200"/>
<ComboBoxItem Content="38400"/>
<ComboBoxItem Content="57600"/>
<ComboBoxItem Content="115200"/>
</ComboBox>
</StackPanel>
<StackPanel Orientation="Horizontal">
<Button x:Name="HomeNetConnectBtn" Content="연결" Style="{StaticResource ModernButton}" Click="HomeNetConnect_Click" Padding="12,5" Margin="0,0,4,0"/>
<Button x:Name="HomeNetDisconnectBtn" Content="해제" Style="{StaticResource ModernButton}" Click="HomeNetDisconnect_Click" Padding="12,5"
Background="{StaticResource AccentRedBrush}"/>
<Ellipse x:Name="HomeNetStatus" Width="10" Height="10" Margin="10,0,4,0" Fill="#F7768E" VerticalAlignment="Center"/>
<TextBlock x:Name="HomeNetStatusText" Text="미연결" Foreground="{StaticResource TextSecondaryBrush}" VerticalAlignment="Center" FontSize="11"/>
</StackPanel>
</StackPanel>
</Border>
<!-- Diffuser (DiffuserSimulator 센서 수신) -->
<Border Style="{StaticResource InnerCard}" Margin="0,0,6,0" Padding="8,6">
<StackPanel>
<StackPanel Orientation="Horizontal" Margin="0,0,0,5">
<TextBlock Text="Diffuser" Foreground="{StaticResource TextPrimaryBrush}" VerticalAlignment="Center"
Width="62" FontSize="11" FontWeight="SemiBold"/>
<ComboBox x:Name="DiffuserPortCombo" Width="92" Style="{StaticResource ModernComboBox}" Margin="0,0,6,0"/>
<TextBlock Text="115200 8N1" Foreground="{StaticResource TextSecondaryBrush}" VerticalAlignment="Center" FontSize="11"/>
</StackPanel>
<StackPanel Orientation="Horizontal">
<Button x:Name="DiffuserConnectBtn" Content="연결" Style="{StaticResource ModernButton}" Click="DiffuserConnect_Click" Padding="12,5" Margin="0,0,4,0"/>
<Button x:Name="DiffuserDisconnectBtn" Content="해제" Style="{StaticResource ModernButton}" Click="DiffuserDisconnect_Click" Padding="12,5"
Background="{StaticResource AccentRedBrush}"/>
<Ellipse x:Name="DiffuserStatus" Width="10" Height="10" Margin="10,0,4,0" Fill="#F7768E" VerticalAlignment="Center"/>
<TextBlock x:Name="DiffuserStatusText" Text="미연결" Foreground="{StaticResource TextSecondaryBrush}" VerticalAlignment="Center" FontSize="11"/>
</StackPanel>
</StackPanel>
</Border>
<!-- Hood (후드메인 연동 - HOOD 프로토콜 Rev1.3) -->
<Border Style="{StaticResource InnerCard}" Padding="8,6">
<StackPanel>
<StackPanel Orientation="Horizontal" Margin="0,0,0,5">
<TextBlock Text="Hood" Foreground="{StaticResource TextPrimaryBrush}" VerticalAlignment="Center"
Width="62" FontSize="11" FontWeight="SemiBold"/>
<ComboBox x:Name="HoodPortCombo" Width="92" Style="{StaticResource ModernComboBox}" Margin="0,0,6,0"/>
<TextBlock Text="115200 8N1" Foreground="{StaticResource TextSecondaryBrush}" VerticalAlignment="Center" FontSize="11"/>
</StackPanel>
<StackPanel Orientation="Horizontal">
<Button x:Name="HoodConnectBtn" Content="연결" Style="{StaticResource ModernButton}" Click="HoodConnect_Click" Padding="12,5" Margin="0,0,4,0"/>
<Button x:Name="HoodDisconnectBtn" Content="해제" Style="{StaticResource ModernButton}" Click="HoodDisconnect_Click" Padding="12,5"
Background="{StaticResource AccentRedBrush}"/>
<Ellipse x:Name="HoodStatus" Width="10" Height="10" Margin="10,0,4,0" Fill="#F7768E" VerticalAlignment="Center"/>
<TextBlock x:Name="HoodStatusText" Text="미연결" Foreground="{StaticResource TextSecondaryBrush}" VerticalAlignment="Center" FontSize="11"/>
</StackPanel>
</StackPanel>
</Border>
</UniformGrid>
<StackPanel Orientation="Horizontal" HorizontalAlignment="Right" Margin="0,6,0,0">
<Button Content="⟳ 포트 새로고침" Style="{StaticResource ModernButton}" Click="RefreshPorts_Click"
Background="{StaticResource CardBgBrush}" Padding="10,4" FontSize="11"/>
</StackPanel>
</StackPanel>
</Grid>
</Border>
<!-- Row 1: 전원 + 운전 모드 + 에러 코드 -->
<Grid Grid.Row="1">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<Border Grid.Column="0" Style="{StaticResource SectionCard}" Margin="0,0,8,8">
<StackPanel>
<TextBlock Text="전원" Style="{StaticResource SectionTitle}"/>
<StackPanel Orientation="Horizontal">
<Border x:Name="PowerOnCard" Width="80" Padding="10,6" CornerRadius="6"
Background="{StaticResource CardBgBrush}" BorderBrush="{StaticResource BorderBrush}" BorderThickness="1" Margin="0,0,6,0">
<TextBlock Text="ON" HorizontalAlignment="Center" FontWeight="Bold" FontSize="16"
Foreground="{StaticResource TextSecondaryBrush}"/>
</Border>
<Border x:Name="PowerOffCard" Width="80" Padding="10,6" CornerRadius="6"
Background="{StaticResource CardBgBrush}" BorderBrush="{StaticResource BorderBrush}" BorderThickness="1">
<TextBlock Text="OFF" HorizontalAlignment="Center" FontWeight="Bold" FontSize="16"
Foreground="{StaticResource TextSecondaryBrush}"/>
</Border>
</StackPanel>
</StackPanel>
</Border>
<Border Grid.Column="1" Style="{StaticResource SectionCard}" Margin="0,0,8,8">
<StackPanel>
<TextBlock Text="운전 모드" Style="{StaticResource SectionTitle}"/>
<!-- 운전모드 + 풍량 + (꺼짐)예약 한 줄 -->
<StackPanel Orientation="Horizontal">
<StackPanel Orientation="Horizontal" x:Name="ModePanel" VerticalAlignment="Center">
<Button Content="환기" Tag="Ventilation" Click="ModeButton_Click" Style="{StaticResource ModernButton}" Margin="0,0,6,0" MinWidth="70"
Background="{StaticResource CardBgBrush}"/>
<Button Content="자동" Tag="Auto" Click="ModeButton_Click" Style="{StaticResource ModernButton}" Margin="0,0,6,0" MinWidth="70"
Background="{StaticResource CardBgBrush}"/>
<Button Content="공청" Tag="AirClean" Click="ModeButton_Click" Style="{StaticResource ModernButton}" Margin="0,0,6,0" MinWidth="70"
Background="{StaticResource CardBgBrush}"/>
<Button Content="바이패스" Tag="Bypass" Click="ModeButton_Click" Style="{StaticResource ModernButton}" Margin="0,0,0,0" MinWidth="70"
Background="{StaticResource CardBgBrush}"/>
</StackPanel>
<TextBlock Text="풍량" Foreground="{StaticResource TextPrimaryBrush}" VerticalAlignment="Center" FontSize="12" FontWeight="SemiBold" Margin="18,0,8,0"/>
<StackPanel Orientation="Horizontal" x:Name="FanPanel" VerticalAlignment="Center">
<Button Content="0" Tag="0" Click="FanButton_Click" Style="{StaticResource ModernButton}" Margin="0,0,4,0" MinWidth="42" Background="{StaticResource CardBgBrush}"/>
<Button Content="1" Tag="1" Click="FanButton_Click" Style="{StaticResource ModernButton}" Margin="0,0,4,0" MinWidth="42" Background="{StaticResource CardBgBrush}"/>
<Button Content="2" Tag="2" Click="FanButton_Click" Style="{StaticResource ModernButton}" Margin="0,0,4,0" MinWidth="42" Background="{StaticResource CardBgBrush}"/>
<Button Content="3" Tag="3" Click="FanButton_Click" Style="{StaticResource ModernButton}" Margin="0,0,4,0" MinWidth="42" Background="{StaticResource CardBgBrush}"/>
<Button Content="4" Tag="4" Click="FanButton_Click" Style="{StaticResource ModernButton}" Margin="0,0,0,0" MinWidth="42" Background="{StaticResource CardBgBrush}"/>
</StackPanel>
<TextBlock Text="예약(꺼짐)" Foreground="{StaticResource TextPrimaryBrush}" VerticalAlignment="Center" FontSize="12" FontWeight="SemiBold" Margin="18,0,8,0"/>
<ComboBox x:Name="ReserveCombo" Width="90" Style="{StaticResource ModernComboBox}" VerticalAlignment="Center" SelectionChanged="ReserveCombo_Changed" SelectedIndex="0">
<ComboBoxItem Content="해제"/>
<ComboBoxItem Content="1시간"/>
<ComboBoxItem Content="2시간"/>
<ComboBoxItem Content="3시간"/>
<ComboBoxItem Content="4시간"/>
<ComboBoxItem Content="5시간"/>
<ComboBoxItem Content="6시간"/>
<ComboBoxItem Content="7시간"/>
<ComboBoxItem Content="8시간"/>
</ComboBox>
<TextBlock x:Name="ReserveText" Text="예약 없음" Foreground="{StaticResource AccentYellowBrush}" VerticalAlignment="Center" FontSize="12" Margin="10,0,0,0"/>
</StackPanel>
<!-- 자동모드 프리셋(절전/표준/쾌속) : 자동 선택 시에만 활성, 기본 표준(NORMAL).
선택 프리셋이 공기질 판정 임계(=히스테리시스 임계)를 결정. Tag=프리셋 인덱스 0/1/2 -->
<StackPanel Orientation="Horizontal" x:Name="PresetPanel" Margin="0,8,0,0" VerticalAlignment="Center">
<Button Content="절전 (ECO)" Tag="0" Click="PresetButton_Click" Style="{StaticResource ModernButton}" Margin="0,0,6,0" MinWidth="96" Background="{StaticResource CardBgBrush}"/>
<Button Content="표준 (NORMAL)" Tag="1" Click="PresetButton_Click" Style="{StaticResource ModernButton}" Margin="0,0,6,0" MinWidth="96" Background="{StaticResource CardBgBrush}"/>
<Button Content="쾌속 (TURBO)" Tag="2" Click="PresetButton_Click" Style="{StaticResource ModernButton}" Margin="0,0,16,0" MinWidth="96" Background="{StaticResource CardBgBrush}"/>
<!-- 공기질 센서 히스테리시스 + 풍량 VSP + 후드연동 (쾌속 옆) -->
<Button Content="공기질 센서 히스테리시스 ▸" Click="OpenHyst_Click" Style="{StaticResource ModernButton}" Margin="0,0,6,0" MinWidth="84" Background="{StaticResource CardBgBrush}"/>
<Button Content="풍량 VSP ▸" Click="OpenVsp_Click" Style="{StaticResource ModernButton}" Margin="0,0,6,0" Padding="12,4" Background="{StaticResource CardBgBrush}"/>
<Button x:Name="HoodLinkBtn" Content="후드연동" IsHitTestVisible="False" Style="{StaticResource ModernButton}"
Padding="12,4" Background="{StaticResource CardBgBrush}" Foreground="{StaticResource TextPrimaryBrush}"/>
<Ellipse x:Name="HoodCommLed" Width="9" Height="9" Fill="#F7768E" VerticalAlignment="Center" Margin="8,0,5,0"/>
<TextBlock x:Name="HoodCommText" Text="후드 통신 안됨" FontSize="11" FontWeight="SemiBold"
Foreground="{StaticResource TextSecondaryBrush}" VerticalAlignment="Center"/>
</StackPanel>
</StackPanel>
</Border>
<!-- 에러 코드 (운전모드 옆, 클릭 토글) -->
<Border Grid.Column="2" Style="{StaticResource SectionCard}" Margin="0,0,0,8">
<StackPanel>
<DockPanel Margin="0,0,0,4">
<TextBlock Text="에러 코드" Style="{StaticResource SectionTitle}" Margin="0"/>
<TextBlock x:Name="ErrorCodeHex" DockPanel.Dock="Right" Style="{StaticResource FieldValue}"
VerticalAlignment="Center" Margin="10,0,0,0" Foreground="{StaticResource TextSecondaryBrush}"/>
</DockPanel>
<StackPanel Orientation="Horizontal">
<Border x:Name="ErrCard_E02" Tag="E02" MouseDown="ErrorCard_Click" Cursor="Hand" CornerRadius="4" Padding="6,3" Margin="0,0,4,0"
Background="{StaticResource CardBgBrush}" BorderBrush="{StaticResource BorderBrush}" BorderThickness="1" ToolTip="온도센서 에러">
<StackPanel Orientation="Horizontal">
<Ellipse x:Name="ErrLed_E02" Width="9" Height="9" Fill="#3B3B55" VerticalAlignment="Center" Margin="0,0,4,0"/>
<TextBlock Text="E02" FontSize="11" FontWeight="Bold" VerticalAlignment="Center" Foreground="{StaticResource TextPrimaryBrush}"/>
</StackPanel>
</Border>
<Border x:Name="ErrCard_E09" Tag="E09" MouseDown="ErrorCard_Click" Cursor="Hand" CornerRadius="4" Padding="6,3" Margin="0,0,4,0"
Background="{StaticResource CardBgBrush}" BorderBrush="{StaticResource BorderBrush}" BorderThickness="1" ToolTip="급기(SA) 팬 에러">
<StackPanel Orientation="Horizontal">
<Ellipse x:Name="ErrLed_E09" Width="9" Height="9" Fill="#3B3B55" VerticalAlignment="Center" Margin="0,0,4,0"/>
<TextBlock Text="E09" FontSize="11" FontWeight="Bold" VerticalAlignment="Center" Foreground="{StaticResource TextPrimaryBrush}"/>
</StackPanel>
</Border>
<Border x:Name="ErrCard_E10" Tag="E10" MouseDown="ErrorCard_Click" Cursor="Hand" CornerRadius="4" Padding="6,3" Margin="0,0,4,0"
Background="{StaticResource CardBgBrush}" BorderBrush="{StaticResource BorderBrush}" BorderThickness="1" ToolTip="배기(EA) 팬 에러">
<StackPanel Orientation="Horizontal">
<Ellipse x:Name="ErrLed_E10" Width="9" Height="9" Fill="#3B3B55" VerticalAlignment="Center" Margin="0,0,4,0"/>
<TextBlock Text="E10" FontSize="11" FontWeight="Bold" VerticalAlignment="Center" Foreground="{StaticResource TextPrimaryBrush}"/>
</StackPanel>
</Border>
<Border x:Name="ErrCard_COLD" Tag="COLD" MouseDown="ErrorCard_Click" Cursor="Hand" CornerRadius="4" Padding="6,3" Margin="0,0,4,0"
Background="{StaticResource CardBgBrush}" BorderBrush="{StaticResource BorderBrush}" BorderThickness="1" ToolTip="장비보호모드">
<StackPanel Orientation="Horizontal">
<Ellipse x:Name="ErrLed_COLD" Width="9" Height="9" Fill="#3B3B55" VerticalAlignment="Center" Margin="0,0,4,0"/>
<TextBlock Text="COLD" FontSize="11" FontWeight="Bold" VerticalAlignment="Center" Foreground="{StaticResource TextPrimaryBrush}"/>
</StackPanel>
</Border>
<Border x:Name="ErrCard_E07" Tag="E07" MouseDown="ErrorCard_Click" Cursor="Hand" CornerRadius="4" Padding="6,3"
Background="{StaticResource CardBgBrush}" BorderBrush="{StaticResource BorderBrush}" BorderThickness="1" ToolTip="내부 통신 에러">
<StackPanel Orientation="Horizontal">
<Ellipse x:Name="ErrLed_E07" Width="9" Height="9" Fill="#3B3B55" VerticalAlignment="Center" Margin="0,0,4,0"/>
<TextBlock Text="E07" FontSize="11" FontWeight="Bold" VerticalAlignment="Center" Foreground="{StaticResource TextPrimaryBrush}"/>
</StackPanel>
</Border>
</StackPanel>
<!-- 알람(유지보수) : 필터 청소/교환 -->
<StackPanel Orientation="Horizontal" Margin="0,5,0,0">
<Border x:Name="ErrCard_FCLEAN" Tag="FCLEAN" MouseDown="ErrorCard_Click" Cursor="Hand" CornerRadius="4" Padding="6,3" Margin="0,0,4,0"
Background="{StaticResource CardBgBrush}" BorderBrush="{StaticResource BorderBrush}" BorderThickness="1" ToolTip="필터 청소 알람">
<StackPanel Orientation="Horizontal">
<Ellipse x:Name="ErrLed_FCLEAN" Width="9" Height="9" Fill="#3B3B55" VerticalAlignment="Center" Margin="0,0,4,0"/>
<TextBlock Text="필터청소" FontSize="11" FontWeight="Bold" VerticalAlignment="Center" Foreground="{StaticResource TextPrimaryBrush}"/>
</StackPanel>
</Border>
<Border x:Name="ErrCard_FCHANGE" Tag="FCHANGE" MouseDown="ErrorCard_Click" Cursor="Hand" CornerRadius="4" Padding="6,3"
Background="{StaticResource CardBgBrush}" BorderBrush="{StaticResource BorderBrush}" BorderThickness="1" ToolTip="필터 교환 알람">
<StackPanel Orientation="Horizontal">
<Ellipse x:Name="ErrLed_FCHANGE" Width="9" Height="9" Fill="#3B3B55" VerticalAlignment="Center" Margin="0,0,4,0"/>
<TextBlock Text="필터교환" FontSize="11" FontWeight="Bold" VerticalAlignment="Center" Foreground="{StaticResource TextPrimaryBrush}"/>
</StackPanel>
</Border>
</StackPanel>
</StackPanel>
</Border>
</Grid>
<!-- Row 2: 본체 댐퍼 (6개) -->
<Border Grid.Row="2" Style="{StaticResource SectionCard}">
<StackPanel>
<TextBlock Text="댐퍼 동작 (본체)" Style="{StaticResource SectionTitle}"/>
<ItemsControl x:Name="DamperItems">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<UniformGrid Columns="6"/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<Border Style="{StaticResource InnerCard}">
<StackPanel>
<DockPanel>
<Border DockPanel.Dock="Left" Width="14" Height="14" CornerRadius="7"
Background="{Binding ColorTag, Converter={StaticResource TagBrush}}"
BorderBrush="{StaticResource BorderBrush}" BorderThickness="1" Margin="0,0,6,0"/>
<TextBlock Text="{Binding Name}" FontWeight="Bold" Foreground="{StaticResource TextPrimaryBrush}"/>
</DockPanel>
<TextBlock Text="{Binding Connector}" Foreground="{StaticResource TextSecondaryBrush}" FontSize="11"/>
<TextBlock FontSize="11" Foreground="{StaticResource TextPrimaryBrush}" FontFamily="Consolas">
<Run Text="각도: "/>
<Run Text="{Binding TargetAngle, Mode=OneWay}"/>
<Run Text="°"/>
</TextBlock>
<TextBlock FontWeight="Bold" Margin="0,4,0,0" FontSize="13"
Text="{Binding IsOpen, Converter={StaticResource BoolOC}}"
Foreground="{Binding IsOpen, Converter={StaticResource BoolBrush}}"/>
</StackPanel>
</Border>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</StackPanel>
</Border>
<!-- Row 3: DL 각실제어 (시나리오모드 + 자동운전 상태) -->
<Border Grid.Row="3" Style="{StaticResource SectionCard}">
<StackPanel>
<TextBlock Text="DL 각실제어" Style="{StaticResource SectionTitle}"/>
<!-- 시나리오모드 -->
<StackPanel Orientation="Horizontal" Margin="0,2,0,0" x:Name="SubModePanel">
<TextBlock Text="시나리오모드" Foreground="{StaticResource TextPrimaryBrush}" VerticalAlignment="Center" Width="84" FontSize="12" FontWeight="SemiBold"/>
<Button Content="스마트수면" Tag="Sleep" Click="SubModeButton_Click" Style="{StaticResource ModernButton}" Margin="0,0,6,0" MinWidth="84" Background="{StaticResource CardBgBrush}"/>
<Button Content="쾌적조리" Tag="Cook" Click="SubModeButton_Click" Style="{StaticResource ModernButton}" Margin="0,0,6,0" MinWidth="84" Background="{StaticResource CardBgBrush}"/>
<Button Content="안심회복" Tag="Recovery" Click="SubModeButton_Click" Style="{StaticResource ModernButton}" Margin="0,0,16,0" MinWidth="84" Background="{StaticResource CardBgBrush}"/>
</StackPanel>
<!-- 자동운전 상태 -->
<DockPanel Margin="0,10,0,4">
<TextBlock Text="자동운전 상태" FontSize="12" FontWeight="SemiBold" Foreground="{StaticResource TextPrimaryBrush}" VerticalAlignment="Center"/>
<Border DockPanel.Dock="Right" Background="{StaticResource CardBgBrush}" CornerRadius="6" Padding="10,3"
BorderBrush="{StaticResource BorderBrush}" BorderThickness="1">
<TextBlock VerticalAlignment="Center" FontWeight="Bold" FontSize="13" Foreground="{StaticResource AccentCyanBrush}">
<Run Text="동작: "/>
<Run x:Name="AutoStateRun" Text="-"/>
<Run Text=" (분산 / 집중)" Foreground="{StaticResource TextSecondaryBrush}" FontWeight="Normal"/>
</TextBlock>
</Border>
</DockPanel>
<ItemsControl x:Name="RoomLoadItems">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate><UniformGrid Columns="4"/></ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<Border Style="{StaticResource InnerCard}" Margin="3">
<StackPanel>
<TextBlock Text="{Binding Name}" HorizontalAlignment="Center" FontSize="11" Foreground="{StaticResource TextSecondaryBrush}"/>
<TextBlock Text="{Binding Level, Mode=OneWay}" HorizontalAlignment="Center" FontSize="20" FontWeight="Bold" Foreground="{StaticResource AccentBlueBrush}"/>
<TextBlock Text="{Binding SensorText, Mode=OneWay}" HorizontalAlignment="Center" FontSize="9" Foreground="{StaticResource TextSecondaryBrush}" TextWrapping="Wrap"/>
</StackPanel>
</Border>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</StackPanel>
</Border>
<!-- Row 4: 통신 로그 -->
<Border Grid.Row="4" Style="{StaticResource SectionCard}">
<DockPanel>
<Grid DockPanel.Dock="Top" Margin="0,0,0,6">
<TextBlock Text="통신 로그" Style="{StaticResource SectionTitle}" Margin="0"/>
<StackPanel Orientation="Horizontal" HorizontalAlignment="Right">
<Button Content="로그 저장" Style="{StaticResource ModernButton}"
Background="{StaticResource AccentBlueBrush}" Padding="10,3" FontSize="11" Margin="0,0,6,0"
Click="SaveLog_Click"/>
<Button Content="로그 지우기" Style="{StaticResource ModernButton}"
Background="{StaticResource CardBgBrush}" Padding="10,3" FontSize="11"
Click="ClearLog_Click"/>
</StackPanel>
</Grid>
<TextBox x:Name="LogList" IsReadOnly="True" Background="{StaticResource CardBgBrush}"
Foreground="{StaticResource TextPrimaryBrush}" BorderBrush="{StaticResource BorderBrush}"
BorderThickness="1" FontFamily="Consolas" FontSize="11"
VerticalScrollBarVisibility="Auto" HorizontalScrollBarVisibility="Auto"
TextWrapping="NoWrap" Padding="6"/>
</DockPanel>
</Border>
</Grid>
</Window>