Files
HECO2/TestProgram/WebDashBoard/ErvCollector
jeon 096111e983 feat: 06-17 신규 작업본 반영 (개발사양서/기능검토/승인원/Source 등 추가)
.claude/ 제외(.gitignore 추가). 기존 초기커밋(5a96a69) 위에 신규·수정·이동분 커밋.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-18 07:54:58 +09:00
..

ErvCollector — ERV 24시간 수집/저장 + 원격 모니터링·제어 서버 (미니PC)

3개 현장의 EW11(TCP Client)이 보내는 ERV 0xAA STATUS 프레임을 수신·파싱하여 InfluxDB 에 적재(장기 보관)하고, 내장 웹 대시보드 + HTTP API 로 실시간 모니터링과 원격 제어를 제공한다.

[현장1 ERV]─RS485─[EW11]─WiFi/인터넷─┐ TCP 6001
[현장2 ERV]─RS485─[EW11]─WiFi/인터넷─┤ TCP 6002 → [미니PC] ErvCollector ┬ InfluxDB(보관) → Grafana(장기분석)
[현장3 ERV]─RS485─[EW11]─WiFi/인터넷─┘ TCP 6003                          └ HTTP 8080 (웹 대시보드 + 제어 API)

원격 제어 원리: EW11 은 양방향 투명 브리지이므로, 현장 EW11 이 서버로 열어둔 동일 TCP 소켓으로 서버가 CTRL_* 프레임을 역방향 전송하면 EW11 → RS-485 → ERV 로 전달된다(추가 회선 불필요). → ERV 펌웨어(UART1)가 CTRL_* 수신 처리(PC_ERV_Protocol 2.1)를 구현해야 실제 동작한다.

  • 프레임 규격: ../PC_ERV_Protocol.md
  • 현장 구분: 포트 분리(6001/6002/6003 = site01/02/03), 펌웨어/프로토콜 변경 불필요.

1. 저장 정책 (결정 사항)

항목
저장 해상도 10초 주기 + 이산 상태 변화 시 즉시
보관 기간 1년 (InfluxDB 버킷 retention)
스택 InfluxDB OSS 2.x + Grafana
  • 연속값(PM2.5/PM10/VOC/CO2 등)은 10초 주기 샘플.
  • 이산값(전원/운전모드/풍량/부가모드/후드/프리셋/에러코드 + 각실 댐퍼·공기질등급·LED)이 바뀌면 즉시 1건 추가 기록 → 변화 시점 누락 없음.

1.5 원격 모니터링·제어 (HTTP API)

서버는 Http.Prefix(기본 8080)에서 웹 대시보드와 API 를 제공한다.

메서드 경로 설명
GET / 내장 웹 대시보드(wwwroot/index.html) — 3현장 모니터링 + 제어
GET /api/latest 현장별 최신 상태 JSON(온라인 여부 + 글로벌 + 각실)
POST /api/control 제어. 헤더 X-Auth-Token(토큰 설정 시), 본문 JSON

제어 본문 예시

{ "site":"site01", "action":"power",   "value":1 }
{ "site":"site01", "action":"runmode", "value":2 }          // 1환기 2자동 3공청 4바이패스
{ "site":"site01", "action":"fan",     "value":3 }          // 0~4 (자동모드 무시)
{ "site":"site01", "action":"submode", "type":2, "value":1 }// type 1수면 2조리 3회복
{ "site":"site01", "action":"hood",    "value":1 }
{ "site":"site01", "action":"preset",  "value":2 }          // 0 ECO 1 NORMAL 2 TURBO
{ "site":"site01", "action":"hyst", "pm25":30,"pm10":50,"voc":300,"co2":700 }
{ "site":"site01", "action":"damper",  "room":2, "value":1 }// room 1거실 2~4침실
{ "site":"site01", "action":"led",     "room":1, "value":7 }// 0~9

→ 서버가 해당 현장 EW11 소켓으로 CTRL_* 프레임 송신. 응답 {"ok":true} (연결 없으면 503).

보안: 제어는 민감하므로 Http.Token 을 반드시 설정(대시보드 토큰칸/X-Auth-Token). 운영 시 HTTP 포트는 사내망/VPN 으로 제한하고 외부 직노출 금지 권장.

바인딩: Http.Prefix — Linux 미니PC 는 http://*:8080/(전체 인터페이스), Windows 비관리자 테스트는 http://localhost:8080/ 만 가능(+/* 는 관리자 또는 netsh http add urlacl 필요).


2. 데이터 스키마 (InfluxDB measurement)

erv_global (tag: site) power, run_mode, auto_state, fan_mode, sub_mode, hood, hyst_preset, hyst_pm25, hyst_pm10, hyst_voc, hyst_co2, error_code (모두 정수)

erv_room (tag: site, room=1~4) damper, pm25, pm10, voc, co2, air_quality, led_dim, load_score, final_volume (모두 정수)

코드값 의미(run_mode 1환기/2자동/…, air_quality 1매우나쁨~4좋음 등)는 Grafana Value mappings 로 라벨 표시.


3. 미니PC 설치 (Ubuntu 기준)

3.1 .NET 런타임

sudo apt-get update && sudo apt-get install -y dotnet-runtime-10.0   # 또는 dotnet-sdk-10.0

3.2 InfluxDB OSS 2.x

# 설치 (공식 저장소)
curl -s https://repos.influxdata.com/influxdata-archive_compat.key | sudo gpg --dearmor -o /usr/share/keyrings/influxdata.gpg
echo "deb [signed-by=/usr/share/keyrings/influxdata.gpg] https://repos.influxdata.com/debian stable main" | sudo tee /etc/apt/sources.list.d/influxdata.list
sudo apt-get update && sudo apt-get install -y influxdb2
sudo systemctl enable --now influxdb

# 초기 설정 (org=herv, bucket=erv, 보관 1년=8760h)
influx setup --org herv --bucket erv --retention 8760h --username admin --password '<PW>' --force
# 쓰기용 토큰 확인
influx auth list

→ 출력된 토큰을 appsettings.jsonInflux.Token 에 기입.

3.3 Collector 빌드/실행

cd ErvCollector
dotnet publish -c Release -o /opt/erv-collector
# appsettings.json 의 Influx.Token / Sites 포트 확인 후
/opt/erv-collector/ErvCollector

3.4 systemd 등록 (24시간 자동 실행/재시작)

/etc/systemd/system/erv-collector.service

[Unit]
Description=ERV Collector
After=network.target influxdb.service

[Service]
WorkingDirectory=/opt/erv-collector
ExecStart=/opt/erv-collector/ErvCollector
Restart=always
RestartSec=5

[Install]
WantedBy=multi-user.target
sudo systemctl daemon-reload && sudo systemctl enable --now erv-collector
journalctl -u erv-collector -f   # 로그 확인

3.5 Grafana

sudo apt-get install -y grafana && sudo systemctl enable --now grafana-server
# 브라우저 http://<미니PC>:3000 (admin/admin)
# Data source: InfluxDB → Query language Flux → URL http://127.0.0.1:8086 → org=herv, token, default bucket=erv

대시보드: site별 변수(site)로 현장 전환, room별 패널로 PM/CO2/VOC 추이 + 운전모드/에러 상태 표시.


4. EW11 설정 (현장 3대, IOTService 또는 웹)

항목
Serial 115200 / 8 / None / 1
Protocol TCP Client
Server Addr 회사 서버 공인 IP(또는 DDNS 도메인)
Server Port 현장1→6001, 현장2→6002, 현장3→6003
Security AES(16자 키, 서버와 동일) ※ EW11 TLS는 인증서 미검증이라 AES 병행 권장
Keep Alive / Reconnect 활성
Buffer Size ≥ 256 (STATUS 78B 여유)

회사측: 라우터에서 6001~6003 → 미니PC로 포트포워딩. 가능하면 inbound 를 3현장 공인 IP로 제한.


5. 용량 메모

  • 10초 주기 × 3현장 ≈ 연 950만 레코드(이벤트 추가분 포함). InfluxDB 압축 시 연 수백 MB2GB 수준 → 미니PC SSD로 충분.
  • 1년 retention 이면 자동으로 오래된 데이터 만료.

6.5 WSL2 로 임시 구축 (미니PC 구입 전 검증)

WSL2 는 실제 Linux VM 이라 위 3장 Ubuntu 설치 절차(.NET / InfluxDB / Grafana)가 그대로 동작한다. 검증/개발용으로 충분하다. 단 아래 2가지를 챙겨야 한다.

(1) WSL 안에서 서비스 자동 실행 — systemd 활성화

/etc/wsl.conf (WSL 내부)

[boot]
systemd=true

→ Windows PowerShell 에서 wsl --shutdown 후 재시작하면 systemctl 로 influxdb/grafana/erv-collector 를 서비스로 띄울 수 있다.

(2) 외부 EW11 이 WSL 서비스에 접속 — 네트워크 노출

WSL2 는 기본적으로 NAT 라 LAN 의 EW11 이 WSL 내부 포트에 직접 못 붙는다. 둘 중 하나로 해결:

방법 A — Mirrored networking (Windows 11 22H2+, 권장) %UserProfile%\.wslconfig (Windows 측)

[wsl2]
networkingMode=mirrored

wsl --shutdown 후 재시작. WSL 이 호스트 IP 를 공유하므로 EW11 은 Windows PC 의 LAN IP : 6001~6003 으로 바로 접속.

방법 B — portproxy (Windows 10 등) 관리자 PowerShell:

$wsl = (wsl hostname -I).Trim().Split(" ")[0]   # WSL 내부 IP (재부팅 시 변동)
foreach ($p in 6001,6002,6003) {
  netsh interface portproxy add v4tov4 listenport=$p listenaddress=0.0.0.0 connectport=$p connectaddress=$wsl
}

(3) Windows 방화벽 인바운드 허용

New-NetFirewallRule -DisplayName "ERV Collector" -Direction Inbound -Protocol TCP -LocalPort 6001-6003 -Action Allow
New-NetFirewallRule -DisplayName "Grafana"        -Direction Inbound -Protocol TCP -LocalPort 3000      -Action Allow

⚠️ WSL/PC 는 검증용으로 권장. 24시간 양산 운영은 절전/재부팅/업데이트로 끊길 수 있어 전용 미니PC 가 안전하다. 또한 방법 B 의 WSL 내부 IP 는 재부팅마다 바뀌므로 방법 A(mirrored)가 편하다.

(4) 순수 로컬 테스트라면

EW11 없이 같은 PC 에서 데모 프레임만 흘려볼 거면 네트워크 설정 불필요 — 127.0.0.1:6001 로 바로 송신해 검증 가능(앞선 스모크 테스트 방식).


7. 구성 파일 (appsettings.json)

{
  "Influx": { "Url": "http://127.0.0.1:8086", "Org": "herv", "Bucket": "erv", "Token": "<TOKEN>" },
  "SampleIntervalSeconds": 10,
  "Sites": [
    { "Port": 6001, "Name": "site01" },
    { "Port": 6002, "Name": "site02" },
    { "Port": 6003, "Name": "site03" }
  ]
}