096111e983
.claude/ 제외(.gitignore 추가). 기존 초기커밋(5a96a69) 위에 신규·수정·이동분 커밋.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
117 lines
6.6 KiB
C#
117 lines
6.6 KiB
C#
using System;
|
|
using System.ComponentModel;
|
|
using System.Windows;
|
|
using System.Windows.Controls;
|
|
using System.Windows.Media;
|
|
using ErvDashboard.Model;
|
|
using ErvProtocol;
|
|
|
|
namespace ErvDashboard
|
|
{
|
|
// 공기질 센서 히스테리시스 팝업 : 활성 프리셋의 오염단계 임계(0~3단계 상한, 4단계 최악) + 데드밴드 표시·수정
|
|
public partial class HystWindow : Window
|
|
{
|
|
readonly MainWindow _owner;
|
|
readonly DashboardState _state;
|
|
readonly List<Button> _presetButtons = new();
|
|
|
|
static Brush Br(string key) => (Brush)Application.Current.Resources[key];
|
|
|
|
public HystWindow(MainWindow owner, DashboardState state)
|
|
{
|
|
InitializeComponent();
|
|
_owner = owner; _state = state;
|
|
|
|
foreach (var (label, preset) in new[] { ("ECO", HystPreset.Eco), ("NORMAL", HystPreset.Normal), ("TURBO", HystPreset.Turbo) })
|
|
{
|
|
var b = new Button { Content = label, Tag = preset, Width = 96, Style = (Style)FindResource("FlatButton") };
|
|
b.Click += Preset_Click;
|
|
_presetButtons.Add(b);
|
|
PresetPanel.Children.Add(b);
|
|
}
|
|
_state.PropertyChanged += OnStateChanged;
|
|
RefreshPreset();
|
|
}
|
|
|
|
void OnStateChanged(object? s, PropertyChangedEventArgs e)
|
|
{
|
|
if (e.PropertyName == nameof(DashboardState.HystPreset))
|
|
Dispatcher.BeginInvoke(RefreshPreset);
|
|
}
|
|
|
|
void RefreshPreset()
|
|
{
|
|
foreach (var b in _presetButtons)
|
|
{
|
|
bool active = (HystPreset)b.Tag! == _state.HystPreset;
|
|
b.Background = active ? Br("Accent") : Br("CardBg");
|
|
b.Foreground = active ? Brushes.White : Br("TextPrimary");
|
|
b.BorderBrush = active ? Br("Accent") : Br("CardBorder");
|
|
}
|
|
FillGrid((int)_state.HystPreset);
|
|
}
|
|
|
|
// 활성 프리셋 값으로 표 채우기
|
|
void FillGrid(int p)
|
|
{
|
|
TCo2_1.Text = _state.Co2Thr[p][0].ToString(); TCo2_2.Text = _state.Co2Thr[p][1].ToString(); TCo2_3.Text = _state.Co2Thr[p][2].ToString(); TCo2_4.Text = _state.Co2Thr[p][3].ToString();
|
|
TPm25_1.Text = _state.Pm25Thr[p][0].ToString(); TPm25_2.Text = _state.Pm25Thr[p][1].ToString(); TPm25_3.Text = _state.Pm25Thr[p][2].ToString(); TPm25_4.Text = _state.Pm25Thr[p][3].ToString();
|
|
TPm10_1.Text = _state.Pm10Thr[p][0].ToString(); TPm10_2.Text = _state.Pm10Thr[p][1].ToString(); TPm10_3.Text = _state.Pm10Thr[p][2].ToString(); TPm10_4.Text = _state.Pm10Thr[p][3].ToString();
|
|
TVoc_1.Text = _state.VocThr[p][0].ToString(); TVoc_2.Text = _state.VocThr[p][1].ToString(); TVoc_3.Text = _state.VocThr[p][2].ToString(); TVoc_4.Text = _state.VocThr[p][3].ToString();
|
|
var h = _state.HystTable[p];
|
|
DCo2.Text = h.Co2.ToString(); DPm25.Text = h.Pm25.ToString(); DPm10.Text = h.Pm10.ToString(); DVoc.Text = h.Voc.ToString();
|
|
// 4단계(최악) : 3단계 상한 초과 = (상한+1)~ (사양서 10p)
|
|
MCo2.Text = $"{_state.Co2Thr[p][3] + 1}~"; MPm25.Text = $"{_state.Pm25Thr[p][3] + 1}~";
|
|
MPm10.Text = $"{_state.Pm10Thr[p][3] + 1}~"; MVoc.Text = $"{_state.VocThr[p][3] + 1}~";
|
|
}
|
|
|
|
// 사양서 기본값으로 표 채우기 (전송은 '변경'에서) — 개발사양서 p.10
|
|
void FillDefaults(int p)
|
|
{
|
|
TCo2_1.Text = DashboardState.DefCo2Thr[p][0].ToString(); TCo2_2.Text = DashboardState.DefCo2Thr[p][1].ToString(); TCo2_3.Text = DashboardState.DefCo2Thr[p][2].ToString(); TCo2_4.Text = DashboardState.DefCo2Thr[p][3].ToString();
|
|
TPm25_1.Text = DashboardState.DefPm25Thr[p][0].ToString(); TPm25_2.Text = DashboardState.DefPm25Thr[p][1].ToString(); TPm25_3.Text = DashboardState.DefPm25Thr[p][2].ToString(); TPm25_4.Text = DashboardState.DefPm25Thr[p][3].ToString();
|
|
TPm10_1.Text = DashboardState.DefPm10Thr[p][0].ToString(); TPm10_2.Text = DashboardState.DefPm10Thr[p][1].ToString(); TPm10_3.Text = DashboardState.DefPm10Thr[p][2].ToString(); TPm10_4.Text = DashboardState.DefPm10Thr[p][3].ToString();
|
|
TVoc_1.Text = DashboardState.DefVocThr[p][0].ToString(); TVoc_2.Text = DashboardState.DefVocThr[p][1].ToString(); TVoc_3.Text = DashboardState.DefVocThr[p][2].ToString(); TVoc_4.Text = DashboardState.DefVocThr[p][3].ToString();
|
|
var d = DashboardState.DefDeadband[p];
|
|
DCo2.Text = d.Co2.ToString(); DPm25.Text = d.Pm25.ToString(); DPm10.Text = d.Pm10.ToString(); DVoc.Text = d.Voc.ToString();
|
|
MCo2.Text = $"{DashboardState.DefCo2Thr[p][3] + 1}~"; MPm25.Text = $"{DashboardState.DefPm25Thr[p][3] + 1}~";
|
|
MPm10.Text = $"{DashboardState.DefPm10Thr[p][3] + 1}~"; MVoc.Text = $"{DashboardState.DefVocThr[p][3] + 1}~";
|
|
}
|
|
|
|
// '읽어오기' : ERV 통신값(=_state, STATUS로 갱신)으로 표 재채움 (편집 내용 버림)
|
|
void Read_Click(object sender, RoutedEventArgs e) => FillGrid((int)_state.HystPreset);
|
|
|
|
// '프리셋' : 사양서 기본값으로 표 채움 (전송은 '변경')
|
|
void PresetDefault_Click(object sender, RoutedEventArgs e) => FillDefaults((int)_state.HystPreset);
|
|
|
|
static int P(TextBox tb) { int.TryParse(tb.Text, out int v); return v < 0 ? 0 : v > 65535 ? 65535 : v; }
|
|
|
|
void Preset_Click(object sender, RoutedEventArgs e)
|
|
{
|
|
if (sender is Button b && b.Tag is HystPreset p) _owner.SelectPreset(p);
|
|
}
|
|
|
|
void Apply_Click(object sender, RoutedEventArgs e)
|
|
{
|
|
int p = (int)_state.HystPreset;
|
|
// 표 → 상태
|
|
_state.Co2Thr[p][0] = P(TCo2_1); _state.Co2Thr[p][1] = P(TCo2_2); _state.Co2Thr[p][2] = P(TCo2_3); _state.Co2Thr[p][3] = P(TCo2_4);
|
|
_state.Pm25Thr[p][0] = P(TPm25_1); _state.Pm25Thr[p][1] = P(TPm25_2); _state.Pm25Thr[p][2] = P(TPm25_3); _state.Pm25Thr[p][3] = P(TPm25_4);
|
|
_state.Pm10Thr[p][0] = P(TPm10_1); _state.Pm10Thr[p][1] = P(TPm10_2); _state.Pm10Thr[p][2] = P(TPm10_3); _state.Pm10Thr[p][3] = P(TPm10_4);
|
|
_state.VocThr[p][0] = P(TVoc_1); _state.VocThr[p][1] = P(TVoc_2); _state.VocThr[p][2] = P(TVoc_3); _state.VocThr[p][3] = P(TVoc_4);
|
|
var h = _state.HystTable[p];
|
|
h.Co2 = P(DCo2); h.Pm25 = P(DPm25); h.Pm10 = P(DPm10); h.Voc = P(DVoc);
|
|
|
|
_owner.ApplyHystPreset(p);
|
|
}
|
|
|
|
void Close_Click(object sender, RoutedEventArgs e) => Close();
|
|
|
|
protected override void OnClosed(System.EventArgs e)
|
|
{
|
|
_state.PropertyChanged -= OnStateChanged;
|
|
base.OnClosed(e);
|
|
}
|
|
}
|
|
}
|