11 KiB
11 KiB
☀️ SolarPower 태양광 발전 통합 관제 시스템
태양광 발전소의 실시간 발전 데이터를 수집하고 모니터링하는 통합 관제 시스템입니다.
📋 목차
- 시스템 개요
- 전체 아키텍처
- 인프라 구성
- 크롤러 (Synology NAS / PC)
- API 서버 (Oracle Cloud)
- 모바일 앱 (React Native/Expo)
- 데이터베이스 (Supabase)
- 문제 해결 가이드
시스템 개요
지원 발전소
| 호기 | 크롤러 타입 | 모니터링 시스템 | 비고 |
|---|---|---|---|
| 1호기 | NREMS | nrems.co.kr | 1,2호기 통합 계정 |
| 2호기 | NREMS | nrems.co.kr | 인버터별 분리 처리 |
| 3호기 | NREMS | nrems.co.kr | |
| 4호기 | NREMS | nrems.co.kr | |
| 5호기 | KREMC | kremc.kr | JWT 인증, 월 단위 수집 |
| 6호기 | Sun-WMS | sun-wms.com | 암호화된 페이로드, 월 단위 수집 |
| 8호기 | Hyundai | hyundai-es.co.kr | 월별 통계 API 사용 (초고속) |
| 9호기 | NREMS | nrems.co.kr | |
| 10호기 | CMSolar | cmsolar2.kr |
전체 아키텍처
flowchart TD
subgraph 외부시스템["외부 모니터링 시스템"]
NREMS["NREMS<br/>(1,2,3,4,9호기)"]
KREMC["KREMC<br/>(5호기)"]
SUNWMS["Sun-WMS<br/>(6호기)"]
HYUNDAI["Hyundai<br/>(8호기)"]
CMSOLAR["CMSolar<br/>(10호기)"]
end
subgraph CLOUD["Oracle Cloud (CRAWLER & API)"]
FASTAPI["FastAPI Server<br/>(Port 8000)"]
NGINX["Nginx Reverse Proxy<br/>(Port 443)"]
CRAWLER["Python Crawler<br/>(Tailscale Routing)"]
end
subgraph NAS["Synology NAS (Exit Node)"]
TAILSCALE["Tailscale Node<br/>(Home IP Mapping)"]
end
subgraph SUPABASE["Supabase (PostgreSQL)"]
DB_PLANTS["plants 테이블"]
DB_LOGS["solar_logs 테이블"]
DB_DAILY["daily_stats 테이블"]
end
subgraph CLIENT["클라이언트"]
APP["React Native App"]
WEB["Web Browser"]
end
NREMS --> CRAWLER
KREMC --> CRAWLER
SUNWMS --> CRAWLER
HYUNDAI --> CRAWLER
CMSOLAR --> CRAWLER
CRAWLER -.->|Tailscale Tunnel| TAILSCALE
TAILSCALE -.->|Proxy Request| 외부시스템
CRAWLER -->|INSERT| DB_LOGS
CRAWLER -->|UPSERT| DB_DAILY
FASTAPI -->|SELECT| DB_PLANTS
FASTAPI -->|SELECT| DB_LOGS
FASTAPI -->|SELECT| DB_DAILY
NGINX --> FASTAPI
APP -->|HTTPS| NGINX
WEB -->|HTTPS| NGINX
인프라 구성
서버 접속 정보
| 서버 | 용도 | 접속 명령어 |
|---|---|---|
| Oracle Cloud | API 서버 & 크롤러 | ssh -i "~/.ssh/holdem_server.key" ubuntu@140.245.73.212 |
| Synology NAS | 데이터 백업 & Tailscale Exit Node | ssh -p2022 haneulai@192.168.45.151 |
도메인
| 도메인 | 용도 |
|---|---|
https://solorpower.dadot.net |
API 서버 (Nginx 리버스 프록시) |
크롤러 (Oracle Cloud / PC)
위치
d:\dev\etc\SolorPower\crawler\ (Local PC)
/home/ubuntu/SolorPower/crawler/ (Oracle Cloud)
네트워크 구성 (Tailscale)
일부 모니터링 사이트에서 Oracle Cloud IP가 차단되는 문제를 해결하기 위해 Tailscale을 사용하여 네트워크를 구성하였습니다.
- 주 호스트: Oracle Cloud (크롤러 실행)
- Exit Node: Synology NAS (가정용 IP 제공)
- 동작: 크롤링 요청 시 Tailscale 터널을 통해 NAS의 IP를 사용하여 외부 시스템에 접근합니다.
디렉토리 구조
crawler/
├── main.py # 메인 실행 파일 (실시간 수집용)
├── crawler_gui.py # GUI 관리 도구 (과거 데이터 수집용) ← NEW!
├── config.py # 발전소/인증 설정
├── database.py # Supabase 연동
├── fetch_history.py # 과거 데이터 수집 로직
├── .env # 환경 변수 (SUPABASE_URL, SUPABASE_KEY)
└── crawlers/
├── __init__.py # 크롤러 라우팅
├── base.py # 공통 유틸리티
├── nrems.py # NREMS 크롤러
├── kremc.py # KREMC 크롤러
├── sun_wms.py # Sun-WMS 크롤러
├── hyundai.py # Hyundai 크롤러
└── cmsolar.py # CMSolar 크롤러
GUI 관리 도구 (NEW)
과거 데이터를 편리하게 수집하고 복구하기 위한 GUI 도구가 추가되었습니다.
- 실행:
python crawler_gui.py - 기능:
- 발전소별 실시간 상태 확인
- 과거 데이터 수집: 날짜 범위를 지정하여 일별/월별 데이터 일괄 수집
- 로그 정리: 미래 날짜로 잘못 들어간 오염 데이터 삭제 기능
자동 수집 (Cron)
# 30분마다 실행 (Oracle Cloud 환경)
*/30 * * * * cd /home/ubuntu/SolorPower/crawler && /home/ubuntu/SolorPower/crawler/venv/bin/python main.py >> cron.log 2>&1
크롤러별 개선 사항 (2026.01)
- 공통: 미래 날짜 데이터(UTC/KST 혼동)가 저장되는 버그 수정 및 자동 청소 로직 추가.
- NREMS: 일별 데이터 수집 시 월 단위로 분할 요청하여 끊김 방지.
- KREMC: 5호기 인증 토큰 파싱 개선 및 월 단위 배치 수집 적용.
- Sun-WMS: 6호기 세션 유지 및 월 단위 수집 안정화.
- Hyundai: 8호기
getSolraMonthWorkAPI를 활용하여 1년치 데이터를 수십 초 내에 수집하도록 최적화.
API 서버 (Oracle Cloud)
위치
/home/ubuntu/SolorPower/api_server/
환경 설정 (.env)
SUPABASE_URL=https://xxxx.supabase.co
SUPABASE_KEY=eyJhbGciOiJIUzI1NiIsInR5cCI6...
DEBUG=false
서비스 관리
sudo systemctl restart solar-api
API 엔드포인트
| Method | Endpoint | 설명 |
|---|---|---|
| GET | /plants/{plant_id}/stats |
발전소 통계 조회 (일/월/년) |
| GET | /plants/{plant_id}/stats/today |
오늘(또는 특정일) 시간별 상세 조회 |
| POST | /plants/{plant_id}/upload |
엑셀 데이터 업로드 (일간) |
| POST | /plants/{plant_id}/upload/monthly |
엑셀 데이터 업로드 (월간) |
파라미터 설명:
period:day(일별),month(월별),year(연도별)year: (옵션) 조회 기준 연도month: (옵션)period=day시 조회할 월date: (옵션)stats/today시 조회할 날짜 (YYYY-MM-DD)
모바일 앱 & 웹 (React Native/Expo)
위치
d:\dev\etc\SolorPower\app\
주요 기능
- 실시간/통계 통합: 대시보드 및 상세 차트(일/월/년).
- 날짜 네비게이션:
◀ 2026년 1월 ▶등의 컨트롤로 자유로운 과거 데이터 탐색. - 엑셀 업로드:
- 일간:
date,generation또는year, month, day, kwh포맷 지원. - 월간:
year, month, kwh포맷 지원. - 별칭(
발전량,kwh등) 및 셀 병합 처리 지원.
- 일간:
- 반응형 웹 지원: PC/모바일 브라우저 최적화.
웹 앱 배포 가이드 (Web Deployment)
React Native(Expo) 앱을 웹으로 빌드하고 Nginx 서버에 배포하는 과정입니다.
1. 웹 빌드 (Local PC)
cd d:\dev\etc\SolorPower\app
npm run export:web
dist폴더에 정적 웹 파일들이 생성됩니다.
2. 서버 업로드 (SCP)
빌드된 dist 폴더를 Oracle Cloud 서버의 웹 루트로 전송합니다.
(참고: /var/www/html/ 권한 문제로 인해 임시 폴더로 전송 후 sudo로 이동해야 할 수 있습니다)
# 1. 홈 디렉토리로 전송
scp -i "~/.ssh/holdem_server.key" -r dist ubuntu@140.245.73.212:~/dist_temp
# 2. 서버 접속 후 이동
ssh -i "~/.ssh/holdem_server.key" ubuntu@140.245.73.212
sudo rm -rf /var/www/html/dist
sudo mv ~/dist_temp /var/www/html/dist
3. Nginx 설정 (서버 분석 결과)
실제 운영 중인 Nginx 설정 (/etc/nginx/sites-enabled/solorpower)의 핵심 구조입니다.
라우팅 규칙:
- Frontend:
/var/www/html/dist(React Static Files) - Backend:
http://127.0.0.1:8000(FastAPI)/plants(데이터/통계 API)/docs,/openapi.json(API 문서)
server {
listen 80;
server_name solorpower.dadot.net;
# HTTPS 리다이렉트 생략...
listen 443 ssl;
# SSL 인증서 설정 생략...
# 1. React Frontend (정적 파일)
location / {
root /var/www/html/dist;
index index.html;
try_files $uri $uri/ /index.html;
}
# 2. FastAPI Backend (API 프록시)
# plants(데이터), docs(문서) 경로만 백엔드로 토스
location ~ ^/(plants|docs|openapi.json) {
proxy_pass http://127.0.0.1:8000;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
4. 적용
sudo systemctl reload nginx
이제 https://solorpower.dadot.net 에서 배포된 웹 앱을 확인할 수 있습니다.
데이터베이스 (Supabase)
주요 테이블
- plants: 발전소 기본 정보.
- solar_logs: 실시간 발전 로그 (10분/30분 단위).
created_at기준. - daily_stats: 일별 발전량 통계.
date기준. (과거 데이터는 여기에 저장됨) - monthly_stats: 월별 발전량 통계.
month기준.
개발 히스토리
2026-04-22
- 크롤러 인프라 이전: 크롤러 실행 환경을 Synology NAS에서 Oracle Cloud로 이전.
- 네트워크 우회 설정: Oracle Cloud IP 차단 이슈 대응을 위해 Tailscale을 도입, Synology NAS를 Exit Node로 설정하여 가정용 IP로 크롤링 수행.
- 안정성 강화: 클라우드 환경 이전을 통해 NAS 리소스 부하 감소 및 수집 안전성 확보.
2026-01-30
- 데이터 복구 및 안정화: 1월 28-29일 데이터 누락 복구 완료.
- 자동 통계 집계 개선:
daily_summary.py가 날짜 파라미터 없이 실행될 경우 자동으로 '어제' 날짜를 기준으로 집계하도록 수정. (새벽 실행 안전성 확보) - 월간 통계 자동화: 일일 집계 시 해당 월의 마지막 날인 경우, 자동으로
monthly_stats까지 집계/갱신하는 로직 추가. - Git 저장소 분리:
2026-01-28
- Stats API 고도화: 날짜/월 탐색을 위한 파라미터(
month,date) 추가. - 연간 통계 개선: 단일 연도 조회에서 '해당 연도 포함 최근 5년' 조회로 변경.
- 엑셀 업로드 유연성:
year, month, day컬럼이 분리된 파일도 자동 인식 및 처리. - Frontend 개선: 차트 상단 날짜 네비게이션(
◀ ▶) 추가, 조회 기간 범위 표시 강화.
2026-01-27
- Crawler 구조화:
crawler_manager.py도입 (스마트 스케줄링, 학습/최적화 모드). - GUI & Documentation: 관리자 GUI 기능 확장 및
crawler_structure.md문서화. - 과거 데이터 수집 최적화: 모든 크롤러 월 단위 분할 수집 지원.
2026-01-23
- 통계 조회 API 추가 및 엑셀 업로드 API 구현.
2026-01-22
- 대시보드 필드명 매핑 수정.