Files
HECO2/Protocol/HOMENET/260607_PCDashBoard_API_및_프로토콜.md
T
jeon a502322188 chore: HERV 통합 저장소 재초기화 커밋
손상된 .git 히스토리(missing tree)로 재초기화 후 작업트리 전체 커밋.
.claude/ 만 제외(로컬 에이전트 설정). 구 저장소 백업(.git_corrupt_backup/) 포함.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-16 09:32:17 +09:00

11 KiB
Raw Blame History

PCDashBoard ↔ ERV 통신 — API 함수 & 프로토콜 상세 (2026.06.07)

PC 대시보드(ErvDashboard) ↔ ERV 메인보드 통신을 485 프로토콜을 그대로 사용하되 IErvApi 함수로 감싼 구조(인프로세스 API 파사드)로 정리한 문서. 선로 통신은 변함없이 485 프레임이며, UI 코드는 바이트/프레임을 다루지 않고 의미 있는 API 함수만 호출한다.


0. 구조 개요

[MainWindow.xaml.cs (UI)]
        │  _api.SetPower(true) / SetFan(2) / RequestStatus() ...
        ▼
[IErvApi]  ←─ 인터페이스 (TestProgram/PCDashBoard/Api/IErvApi.cs)
        ▼
[SerialErvApi]  ←─ 구현 (Api/SerialErvApi.cs)
        │  CtrlFrame 으로 485 프레임 빌드 / FrameParser 로 STATUS 파싱
        ▼
[SerialChannel] ── RS485 / USB-Serial ── [ERV 메인보드]
  • 송신 : IErvApi.SetXxx()CtrlFrame.Xxx()0xAA … CRC16 프레임 생성 → 시리얼 전송
  • 수신 : 시리얼 바이트 → FrameParserSTATUS(0x81) 디코드 → StatusReceived(StatusRecord) 이벤트
  • UI 매핑 : StatusRecordDashboardStateStatusMapper.Apply()(UI 측)가 담당 → API 는 UI 비종속

파일 구성

파일 역할
PCDashBoard/Api/IErvApi.cs 통신 API 인터페이스(함수/이벤트 정의)
PCDashBoard/Api/SerialErvApi.cs RS485 구현(SerialChannel + FrameParser + CtrlFrame 내장)
PCDashBoard/Api/StatusMapper.cs StatusRecord → DashboardState 매핑
PCDashBoard/Protocol/SerialChannel.cs 시리얼 포트 송수신(byte)
ErvProtocol/CtrlFrame.cs PC→ERV 제어 프레임 빌더
ErvProtocol/StatusDecoder.cs ERV→PC STATUS 디코더
ErvProtocol/FrameParser.cs 0xAA/LEN/CRC 프레임 분리
ErvProtocol/Enums.cs RunMode/SubModeType/HystPreset/AirQuality/AutoState

1. API 함수 (IErvApi)

1.1 연결

함수 / 속성 설명
bool Connect(string port, int baud) 시리얼 연결 (대시보드 기본 115200)
void Disconnect() 연결 해제
bool IsConnected { get; } 연결 여부
static string[] SerialErvApi.GetAvailablePorts() 사용 가능한 COM 포트 목록
event Action<bool> ConnectionChanged 연결 상태 변경 통지

1.2 수신

함수 / 이벤트 설명
event Action<StatusRecord> StatusReceived STATUS(0x81) 디코드 완료 시 발생
event Action<string> Log 프레임 hex / 이벤트 로그
void RequestStatus() STATUS 1회 즉시 요청 (CMD 0x0A)
bool GetRoomStatus(int room, out bool damperSa, out bool damperEa, out AirQuality airQuality, out int led) 최근 STATUS 기준 각실(room 1~4) 급기·배기 댐퍼/공기질/LED 조회. 수신 이력 없거나 room 범위 밖이면 false

1.3 제어 함수 ↔ 프로토콜 CMD 매핑

API 함수 CMD PAYLOAD 비고
SetPower(bool on) 0x01 [onoff] 전원 ON/OFF
SetRunMode(RunMode mode) 0x02 [mode] 환기/자동/공청/바이패스
SetFan(int speed) 0x03 [speed] 0~4, 자동모드 시 무시
SetSubMode(SubModeType type, bool on) 0x04 [type][onoff] 스마트수면/쾌적조리/안심회복
SetHood(bool on) 0x05 [onoff] 연동후드
SetHystPreset(HystPreset preset) 0x06 [preset] ECO/NORMAL/TURBO
SetHystDeadband(int preset, int pm25, int pm10, int voc, int co2) 0x07 [preset][pm25(2)][pm10(2)][voc(2)][co2(2)] 프리셋별 히스(하강) 값
SetDiffuserDamper(int room, int type, bool open) 0x08 [room][type][onoff] room 1~4, type 0=급기(SA)/1=배기(EA)
SetDiffuserLed(int room, int dim) 0x09 [room][dim] dim 0~9
RequestStatus() 0x0A (없음) 상태 요청
SetReset(bool on) 0x0B [onoff] ERV 리셋 토글
SetVsp(int group, int index, int sa, int ea) 0x0C [group][index][sa(2)][ea(2)] 풍량 VSP 1엔트리
SetHystThreshold(int preset, int pollutant, int l1, int l2, int l3, int l4) 0x0D [preset][pollutant][L1(2)][L2(2)][L3(2)][L4(2)] 오염단계 임계
SetReserve(int hours) 0x0E [hours] (꺼짐)예약 0~8시간(0=해제)
  • room : 1=거실, 2=침실1, 3=침실2, 4=침실3
  • type(댐퍼) : 0=급기(SA) / 1=배기(EA)
  • group : 0=환기(Vent) / 1=바이패스(Bypass) / 2=공청(AirClean)
  • pollutant : 0=CO2 / 1=PM2.5 / 2=PM10 / 3=VOC
  • 멀티바이트(2) 값은 빅엔디안

1.4 데모

함수 설명
void InjectDemoStatus(int tick) 합성 STATUS 를 수신 경로로 주입(시리얼 없이 UI 테스트)

1.5 enum 정의 (ErvProtocol/Enums.cs)

RunMode      : Off=0, Vent=1, Auto=2, AirClean=3, Bypass=4
AutoState    : Distribute=0(분산), Focus=1(집중)
HystPreset   : Eco=0, Normal=1, Turbo=2
AirQuality   : VeryBad=1, Bad=2, Normal=3, Good=4
SubModeType  : SmartSleep=1, ComfortCook=2, ReliefRecover=3

2. 사용법

2.1 초기화 / 이벤트 등록

readonly DashboardState _state = new();
readonly IErvApi _api = new SerialErvApi();

// 로그 / 연결상태 / STATUS 수신
_api.Log += Log;
_api.ConnectionChanged += b => Dispatcher.BeginInvoke(() => OnConnectionChanged(b));
_api.StatusReceived += rec => Dispatcher.BeginInvoke(() =>
{
    StatusMapper.Apply(rec, _state);   // StatusRecord → UI 모델
    LogStatusSnapshot();
});

SerialErvApi 이벤트는 시리얼 수신(백그라운드) 스레드에서 발생하므로, UI 갱신은 Dispatcher.BeginInvoke 로 마샬링한다.

2.2 연결 / 상태 요청

var ports = SerialErvApi.GetAvailablePorts();   // COM 목록
_api.Connect("COM3", 115200);                   // 연결
_api.RequestStatus();                           // 최초 STATUS 요청
...
_api.Disconnect();

2.3 제어 송신 (예)

_api.SetPower(true);                       // 전원 ON
_api.SetRunMode(RunMode.Auto);             // 자동
_api.SetFan(2);                            // 풍량 2단
_api.SetSubMode(SubModeType.ComfortCook, true);  // 쾌적조리 ON
_api.SetHood(true);                        // 연동후드 ON
_api.SetReserve(3);                        // 3시간 후 꺼짐 예약
_api.SetDiffuserDamper(1, 0, true);        // 거실 급기(SA) 댐퍼 열림
_api.SetDiffuserDamper(1, 1, false);       // 거실 배기(EA) 댐퍼 닫힘
_api.SetDiffuserLed(2, 5);                 // 침실1 LED 디밍 5

// 풍량 VSP (환기2단 SA/EA)
_api.SetVsp(group:0, index:2, sa:63, ea:61);

// 히스테리시스
_api.SetHystPreset(HystPreset.Normal);
_api.SetHystDeadband(preset:1, pm25:2, pm10:5, voc:5, co2:50);
_api.SetHystThreshold(preset:1, pollutant:0 /*CO2*/, l1:700, l2:1000, l3:1300, l4:1600);

2.4 수신 처리

StatusReceivedStatusMapper.Apply(rec, state)DashboardState(전원/모드/풍량/각실 센서· 댐퍼·LED·부하점수·온습도/VSP/히스테리시스/임계표) 전체가 갱신된다.

각실 일부 항목만 즉시 조회할 때는 GetRoomStatus 사용(최근 수신 STATUS 기준) :

if (_api.GetRoomStatus(1, out bool sa, out bool ea, out AirQuality aq, out int led))
    Console.WriteLine($"거실: 급기={(sa ? "열림" : "닫힘")} 배기={(ea ? "열림" : "닫힘")} 공기질={aq} LED={led}");

3. 프로토콜 상세

3.1 물리계층

  • RS-485 (또는 USB-Serial), 115200 bps, 8 Data, None Parity, 1 Stop (N81)

3.2 공통 프레임 (Rev2.0 — 244byte 고정)

+------+------+----------------+--------+--------+
| STX  | CMD  |   DATA[240]    | CRC_L  | CRC_H  |
+------+------+----------------+--------+--------+
  0xAA   1B       240B 고정       16-bit CRC(LE)
필드 크기 설명
STX 1 고정 0xAA
CMD 1 명령/응답 코드
DATA 240 고정 240byte. 제어는 앞쪽 인자 + 나머지 0 패딩, ERV→PC 는 STATUS/ACK 데이터
CRC 2 CRC-16/MODBUS(poly 0xA001, init 0xFFFF), CMD~DATA(241byte) 범위, 리틀엔디안
  • LEN 필드 폐기. 모든 프레임은 항상 1+1+240+2 = 244byte 고정. 파서는 정해진 바이트 수만 읽고 CRC 검증.
  • 멀티바이트 수치는 빅엔디안(CRC만 리틀엔디안)
  • 프레임 동기 : STX(0xAA) 탐색 + 고정길이 수신 + CRC 검증. 60ms 이상 바이트 공백 시 파서 리셋.

3.3 명령 코드

PC → ERV (제어) : 1.3 표 참조 (0x01~0x0E)

ERV → PC (상태/응답)

CMD 이름 PAYLOAD 설명
0x81 STATUS DATA 240 byte (3.5) 전체 상태 스냅샷 (주기 송신 + REQ_STATUS 응답)
0x82 ACK DATA [echoCmd][result] + 0패딩 제어 수신 응답 result 0=OK / 1=ERR

3.4 값 정의

  • 운전모드 : 0 OFF / 1 환기 / 2 자동 / 3 공청 / 4 바이패스
  • 부가모드 type : 1 스마트수면 / 2 쾌적조리 / 3 안심회복 (STATUS subMode 는 비트맵 bit0/1/2)
  • 공기질 : 1 매우나쁨(빨강) / 2 나쁨(주황) / 3 보통(초록) / 4 좋음(파랑)
  • 자동상태 : 0 분산 / 1 집중
  • 히스 프리셋 : 0 ECO / 1 NORMAL / 2 TURBO

3.5 STATUS(0x81) PAYLOAD 레이아웃 — 총 240 byte

블록 offset 크기 내용
글로벌 0~16 17 power, runMode, autoState, fanMode, subMode, hood, hystPreset, hystPM25(7,2), hystPM10(9,2), hystVOC(11,2), hystCO2(13,2), errorCode(15,2)
각실 ×4 17~72 14×4=56 거실→침실1→2→3, 아래 표
리셋 73 1 reset 토글 0/1
VSP 74~109 4×9=36 환기14, 바이패스, 공청14 의 SA(2)+EA(2)
히스 프리셋표 110~133 8×3=24 ECO/NORMAL/TURBO 의 PM2.5(2)/PM10(2)/VOC(2)/CO2(2)
오염단계 임계표 134~229 32×3=96 프리셋×[CO2,PM2.5,PM10,VOC] 각 L1~L4 u16
각실 온습도 ×4 230~237 2×4=8 실별 Temp(1)+Humi(1)
(꺼짐)예약 238~239 2 잔여 초 u16 (0=예약없음)

각실 블록(14 byte) 상세 (상대 offset)

+off 크기 필드
+0 1 damper 비트맵 (bit0 급기 열림 / bit1 배기 열림)
+1 2 pm25
+3 2 pm10
+5 2 voc
+7 2 co2
+9 1 airQuality (3.4)
+10 1 ledDim (0~9)
+11 2 loadScore (부하점수)
+13 1 finalVolume (최종풍량)

오염단계 임계표(프리셋당 32 byte) : CO2[L1..L4] PM2.5[L1..L4] PM10[L1..L4] VOC[L1..L4] 순, 각 u16(빅엔디안).

계산식 : 17 + 56 + 1 + 36 + 24 + 96 + 8 + 2 = 240

3.6 동작 시나리오

  1. 연결 후 RequestStatus()(0x0A) 송신 → ERV 가 STATUS(0x81) 응답.
  2. ERV 는 약 500ms~1s 주기로 STATUS 자동 송신 → 대시보드 실시간 갱신.
  3. PC 제어 시 해당 CTRL_* 송신 → ERV 가 ACK(0x82) + 다음 STATUS 에 반영.
  4. PC 는 STATUS 수신 시마다 로그(시각 + 전체 상태) 적재.

4. 비고

  • 본 문서의 API(IErvApi) 도입은 전송 방식(485 프로토콜)을 바꾸지 않는다. 호출부를 함수로 캡슐화한 것.
  • IErvApi 는 인터페이스이므로, 향후 다른 전송(예: HTTP) 구현(HttpErvApi)을 추가해 설정으로 교체 가능.
  • 펌웨어(UART1/HOMENET_485) 세부 필드는 상호 합의하여 조정한다. (원본 초안: TestProgram/PC_ERV_Protocol.md)