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,289 @@
# WSL2 설치 → ErvCollector 실행 가이드 (윈도우 PC)
미니PC 구입 전, **윈도우 PC + WSL2(Ubuntu)** 에서 수집/모니터·제어 서버(`ErvCollector`)와
InfluxDB·Grafana 를 띄워 전체 파이프라인을 검증하기 위한 단계별 가이드.
> 대상: `TestProgram/WebDashBoard/ErvCollector`
> 순서대로 복사·붙여넣기 하면 됩니다. (Ubuntu 24.04 기준)
---
## 0. 사전 요약 (무엇을 깔고 띄우나)
| 구성요소 | 역할 | 포트 |
|---|---|---|
| ErvCollector(.NET) | 현장 EW11 TCP 수신 + 웹 대시보드/제어 API | 6001~6003(수집), 8080(HTTP) |
| InfluxDB OSS 2.x | 시계열 데이터 24시간 저장(1년 보관) | 8086 |
| Grafana | 장기 분석 대시보드(선택) | 3000 |
---
## 1. WSL2 + Ubuntu 설치 (Windows PowerShell, 관리자)
```powershell
wsl --install -d Ubuntu-24.04
# 설치 후 재부팅 → Ubuntu 최초 실행 시 사용자/암호 설정
wsl --status # 버전 2 확인
wsl --update
```
이후 명령은 모두 **Ubuntu(WSL) 터미널** 안에서 실행한다.
---
## 2. WSL systemd 활성화 (서비스 자동실행용)
```bash
sudo tee /etc/wsl.conf >/dev/null <<'EOF'
[boot]
systemd=true
EOF
```
```powershell
# Windows PowerShell 에서 WSL 재시작
wsl --shutdown
```
다시 Ubuntu 터미널을 열고 확인:
```bash
systemctl is-system-running # running 또는 degraded 면 OK
```
---
## 3. .NET 10 SDK 설치
```bash
sudo apt-get update
sudo apt-get install -y dotnet-sdk-10.0 || {
# 패키지가 없으면 공식 스크립트로 설치
curl -sSL https://dot.net/v1/dotnet-install.sh | bash /dev/stdin --channel 10.0
echo 'export PATH="$HOME/.dotnet:$PATH"' >> ~/.bashrc && source ~/.bashrc
}
dotnet --version
```
---
## 4. InfluxDB OSS 2.x 설치 + 초기 설정
```bash
# 저장소 등록 및 설치
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 influxdb2-cli
sudo systemctl enable --now influxdb
# 초기 설정 : org=herv, bucket=erv, 보관 1년(8760h), 토큰을 직접 지정
influx setup \
--org herv --bucket erv --retention 8760h \
--username admin --password 'change-this-pw' \
--token herv-erv-token-0001 \
--force
```
> 위 `--token herv-erv-token-0001` 값을 그대로 `appsettings.json` 의 `Influx.Token` 에 넣으면 된다.
> (토큰을 따로 확인하려면 `influx auth list`)
---
## 5. (선택) Grafana 설치
```bash
sudo apt-get install -y apt-transport-https software-properties-common
curl -s https://apt.grafana.com/gpg.key | sudo gpg --dearmor -o /usr/share/keyrings/grafana.gpg
echo "deb [signed-by=/usr/share/keyrings/grafana.gpg] https://apt.grafana.com stable main" \
| sudo tee /etc/apt/sources.list.d/grafana.list
sudo apt-get update && sudo apt-get install -y grafana
sudo systemctl enable --now grafana-server
```
- 브라우저에서 `http://localhost:3000` (초기 admin / admin)
- Connections → Data sources → **InfluxDB** 추가
- Query language: **Flux**
- URL: `http://localhost:8086`
- Organization: `herv`, Token: `herv-erv-token-0001`, Default bucket: `erv`
- 패널 쿼리 예시(거실 PM2.5 추이):
```flux
from(bucket: "erv")
|> range(start: v.timeRangeStart, stop: v.timeRangeStop)
|> filter(fn: (r) => r._measurement == "erv_room" and r._field == "pm25" and r.site == "site01" and r.room == "1")
```
---
## 6. 프로젝트 가져오기
> ⚠️ `ErvCollector` 는 공용 라이브러리 **`ErvProtocol`**(경로상 `HERV/TestProgram/ErvProtocol`)을 프로젝트 참조한다.
> (csproj: `..\..\ErvProtocol\ErvProtocol.csproj`) → 빌드 시 이 폴더가 **상대경로로 함께 있어야** 한다.
**방법 1 — 원본 위치에서 바로 빌드 (가장 간단, 권장)**
```bash
cd /mnt/d/project/nuvoton/HERV/TestProgram/WebDashBoard/ErvCollector
# ../../ErvProtocol 가 /mnt/d/.../HERV/TestProgram/ErvProtocol 로 자동 해석됨
```
> `/mnt` 는 다소 느리지만 경로 문제 없이 동작.
**방법 2 — 리눅스 홈으로 복사 (빌드 빠름, 상대구조 유지 필수)**
```bash
mkdir -p ~/herv
cp -r /mnt/d/project/nuvoton/HERV/TestProgram/ErvProtocol ~/herv/ErvProtocol
cp -r /mnt/d/project/nuvoton/HERV/TestProgram/WebDashBoard ~/herv/WebDashBoard
cd ~/herv/WebDashBoard/ErvCollector
# ../../ErvProtocol → ~/herv/ErvProtocol (깊이 일치) ✓
```
### appsettings.json 수정
```bash
nano appsettings.json
```
- `Influx.Token` → `herv-erv-token-0001` (4장에서 지정한 값)
- `Http.Prefix` → 로컬 검증은 `http://localhost:8080/`, **LAN 의 EW11 접속까지** 받으려면 `http://*:8080/`
- (권장) `Http.Token` → 임의의 제어 인증 토큰 지정
---
## 7. 빌드 & 실행
```bash
# 6장에서 정한 ErvCollector 폴더에서 (방법1: /mnt/d/... , 방법2: ~/herv/WebDashBoard/ErvCollector)
dotnet run # 참조된 ErvProtocol 라이브러리도 자동으로 함께 빌드됨
```
정상 기동 로그:
```
ErvCollector 시작. Influx=http://127.0.0.1:8086 bucket=erv 샘플주기=10s
HTTP 대시보드/제어 ← http://localhost:8080/
현장 'site01' ← TCP 포트 6001 대기
현장 'site02' ← TCP 포트 6002 대기
현장 'site03' ← TCP 포트 6003 대기
```
→ **Windows 브라우저**에서 `http://localhost:8080/` 접속(WSL localhost 는 Windows 와 공유됨).
---
## 8. 동작 검증 (EW11 없이)
`ErvCollector` 실행 중인 상태에서, **다른 Ubuntu 터미널**을 열고 데모 STATUS 프레임을 주입:
```bash
python3 - <<'PY'
import socket
# STATUS(0x81) 78바이트 예시 프레임 (PC_ERV_Protocol.md)
frame = bytes.fromhex(("AA 81 49 01 02 01 03 01 01 01 00 1E 00 32 01 2C 02 BC 00 00 "
"01 00 16 00 23 00 B4 02 6C 03 05 00 2A 03 00 00 30 00 46 02 08 03 84 02 03 00 58 04 "
"01 00 0C 00 12 00 5A 01 E0 04 00 00 0F 01 00 00 21 00 37 01 2C 02 D0 02 09 00 3C 02 EB 43").replace(" ",""))
s=socket.create_connection(("127.0.0.1",6001)) # 현장1 포트
import time
for _ in range(20):
s.sendall(frame); time.sleep(1) # 1초마다 1프레임
s.close()
PY
```
확인:
```bash
# 최신 상태 JSON (site01 online:true 로 채워짐)
curl -s http://localhost:8080/api/latest | head -c 400; echo
# 제어 테스트 (전원 OFF 프레임을 site01 소켓으로 송신 → 콜렉터 로그에 '송신' 찍힘)
curl -s -X POST http://localhost:8080/api/control \
-H "Content-Type: application/json" \
-H "X-Auth-Token: <설정한 Http.Token, 없으면 생략>" \
-d '{"site":"site01","action":"power","value":0}'
```
- 브라우저 `http://localhost:8080/` 상단 칩이 **서버연동**, 현장1 점이 초록(온라인)으로 표시.
- InfluxDB 적재 확인:
```bash
influx query 'from(bucket:"erv") |> range(start:-10m) |> filter(fn:(r)=>r._measurement=="erv_room") |> limit(n:5)'
```
---
## 9. (선택) 24시간 자동 실행 — systemd 서비스
```bash
# ErvCollector 폴더에서 게시(참조 ErvProtocol 포함 단일 폴더로 묶임)
dotnet publish -c Release -o ~/erv-publish
sudo tee /etc/systemd/system/erv-collector.service >/dev/null <<EOF
[Unit]
Description=ERV Collector
After=network.target influxdb.service
[Service]
WorkingDirectory=$HOME/erv-publish
ExecStart=$HOME/erv-publish/ErvCollector
Restart=always
RestartSec=5
[Install]
WantedBy=multi-user.target
EOF
sudo systemctl daemon-reload
sudo systemctl enable --now erv-collector
journalctl -u erv-collector -f # 실시간 로그
```
---
## 10. 외부 EW11(LAN) 에서 WSL 서비스로 접속하게 만들기
WSL2 는 기본 NAT 라 LAN 의 EW11 이 WSL 내부 포트에 직접 못 붙는다. 둘 중 하나:
**방법 A — Mirrored networking (Windows 11 22H2+, 권장)**
`%UserProfile%\.wslconfig` (Windows 측, 메모장):
```ini
[wsl2]
networkingMode=mirrored
```
```powershell
wsl --shutdown
```
→ WSL 이 호스트 IP 공유 → EW11 은 **윈도우 PC LAN IP : 6001~6003** 으로 접속. `appsettings.json` 의 `Http.Prefix` 도 `http://*:8080/` 권장.
**방법 B — portproxy (Windows 10)**
관리자 PowerShell:
```powershell
$wsl = (wsl hostname -I).Trim().Split(" ")[0]
foreach ($p in 6001,6002,6003,8080) {
netsh interface portproxy add v4tov4 listenport=$p listenaddress=0.0.0.0 connectport=$p connectaddress=$wsl
}
```
> 방법 B 의 WSL 내부 IP 는 재부팅마다 바뀌므로 재실행 필요(방법 A 가 편함).
**Windows 방화벽 인바운드 허용** (관리자 PowerShell):
```powershell
New-NetFirewallRule -DisplayName "ERV Collector" -Direction Inbound -Protocol TCP -LocalPort 6001-6003 -Action Allow
New-NetFirewallRule -DisplayName "ERV Web" -Direction Inbound -Protocol TCP -LocalPort 8080 -Action Allow
```
EW11(IOTService) 설정: TCP Client / Server=윈도우 PC IP / Port=현장별 6001~6003 / 115200 8N1 / AES / Keepalive.
---
## 11. 종료 · 재시작 · 트러블슈팅
```bash
# 서비스 제어
sudo systemctl restart erv-collector
sudo systemctl status influxdb grafana-server erv-collector
# 포트 점유 확인
ss -ltnp | grep -E '6001|6002|6003|8080|8086'
```
| 증상 | 원인 / 조치 |
|---|---|
| `HTTP 서버 시작 실패` | `Http.Prefix` 가 `+`/`*` 인데 권한 부족 → WSL(Linux)에선 보통 OK. Windows 직접 실행 시 `localhost` 사용 |
| `Influx write FAIL: 연결 거부` | InfluxDB 미기동 → `sudo systemctl start influxdb`, 토큰/org/bucket 확인 |
| 브라우저에서 8080 접속 안됨 | WSL localhost 공유는 보통 자동. 안되면 `wsl --shutdown` 후 재시도 / 방화벽 |
| EW11 이 못 붙음 | 10장(mirrored/portproxy + 방화벽), `Http.Prefix=http://*:8080/`, 같은 서브넷 여부 |
| `dotnet` 없음 | 3장 재확인, `source ~/.bashrc` |
---
## 12. 참고 문서
- 수집서버 상세: `ErvCollector/README.md`
- 프레임 규격: `../TestProgram/PC_ERV_Protocol.md`
- EW11 클라우드 전송 검토: `../EW11_RS485 TO WIFI/260603_EW11_클라우드전송_검토.md`