Files
HECO2/TestProgram/ErvProtocol/StatusDecoder.cs
T
jeon 5a96a696b1 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>
2026-06-15 21:44:23 +09:00

98 lines
3.7 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
namespace ErvProtocol
{
public static class StatusDecoder
{
public const byte STATUS = 0x81; // ERV→PC 상태
public const byte ACK = 0x82; // ERV→PC 제어 응답
public const int STATUS_LEN = 240; // 238 + 2((꺼짐)예약 잔여초 u16)
public const int THR_OFF = 134; // 모드별 오염단계 임계표 시작 오프셋
public const int TEMPHUMI_OFF = 230; // 각실 온도/습도 블록 시작 (4실 × [Temp,Humi])
public const int RESERVE_OFF = 238; // (꺼짐)예약 잔여초 u16
static int U16(byte[] p, int off) => (p[off] << 8) | p[off + 1]; // 빅엔디안
// STATUS(0x81) payload(73B) → StatusRecord. 길이 부족 시 null.
public static StatusRecord? Decode(byte[] p)
{
if (p.Length < STATUS_LEN) return null;
var s = new StatusRecord
{
Power = p[0],
RunMode = p[1],
AutoState = p[2],
FanMode = p[3],
SubMode = p[4],
Hood = p[5],
HystPreset = p[6],
HystPm25 = U16(p, 7),
HystPm10 = U16(p, 9),
HystVoc = U16(p, 11),
HystCo2 = U16(p, 13),
ErrorCode = U16(p, 15),
};
const int baseOff = 17;
for (int r = 0; r < 4; r++)
{
int o = baseOff + r * 14;
var room = s.Rooms[r];
room.Damper = p[o + 0];
room.Pm25 = U16(p, o + 1);
room.Pm10 = U16(p, o + 3);
room.Voc = U16(p, o + 5);
room.Co2 = U16(p, o + 7);
room.AirQuality = p[o + 9];
room.LedDim = p[o + 10];
room.LoadScore = U16(p, o + 11);
room.FinalVolume = p[o + 13];
}
// ERV 리셋 (offset 73)
s.Reset = p[73];
// 풍량 VSP 블록 (offset 74~, 9엔트리 × u16 SA·EA)
const int vspOff = 74;
for (int i = 0; i < 9; i++)
{
int o = vspOff + i * 4;
s.Vsp[i].Sa = U16(p, o);
s.Vsp[i].Ea = U16(p, o + 2);
}
// 히스테리시스 프리셋 테이블 (offset 110~, 3프리셋 × PM2.5/PM10/VOC/CO2 u16)
const int hystOff = 110;
for (int i = 0; i < 3; i++)
{
int o = hystOff + i * 8;
s.HystTable[i].Pm25 = U16(p, o);
s.HystTable[i].Pm10 = U16(p, o + 2);
s.HystTable[i].Voc = U16(p, o + 4);
s.HystTable[i].Co2 = U16(p, o + 6);
}
// 모드별 오염단계 임계표 (offset 134~, 3프리셋 × [CO2,PM2.5,PM10,VOC] × L1~L4 u16)
for (int i = 0; i < 3; i++)
{
int o = THR_OFF + i * 32;
for (int k = 0; k < 4; k++) s.ThrTable[i].Co2[k] = U16(p, o + 0 + k * 2);
for (int k = 0; k < 4; k++) s.ThrTable[i].Pm25[k] = U16(p, o + 8 + k * 2);
for (int k = 0; k < 4; k++) s.ThrTable[i].Pm10[k] = U16(p, o + 16 + k * 2);
for (int k = 0; k < 4; k++) s.ThrTable[i].Voc[k] = U16(p, o + 24 + k * 2);
}
// 각실 온도/습도 (offset 230~, 4실 × [Temp, Humi])
for (int r = 0; r < 4; r++)
{
int o = TEMPHUMI_OFF + r * 2;
s.Rooms[r].Temp = p[o + 0];
s.Rooms[r].Humi = p[o + 1];
}
// (꺼짐)예약 잔여초 (offset 238, u16)
s.ReserveRemainSec = U16(p, RESERVE_OFF);
return s;
}
}
}