feat: implement hybrid daily stats calibration using fetch_history_daily

This commit is contained in:
haneulai 2026-06-15 16:07:32 +09:00
parent 5c504f7747
commit a405748042

View File

@ -13,6 +13,29 @@ except ImportError:
import pandas as pd
from database import get_supabase_client
from config import get_all_plants
def get_history_crawler(plant_type: str):
"""발전소 타입별 과거 데이터 크롤러 함수 반환"""
try:
if plant_type == 'nrems':
from crawlers.nrems import fetch_history_daily
return fetch_history_daily
elif plant_type == 'kremc':
from crawlers.kremc import fetch_history_daily
return fetch_history_daily
elif plant_type == 'hyundai':
from crawlers.hyundai import fetch_history_daily
return fetch_history_daily
elif plant_type == 'sun_wms':
from crawlers.sun_wms import fetch_history_daily
return fetch_history_daily
elif plant_type == 'cmsolar':
from crawlers.cmsolar import fetch_history_daily
return fetch_history_daily
except Exception as e:
print(f" ⚠️ 크롤러 모듈 임포트 실패 ({plant_type}): {e}")
return None
def get_plant_capacities(client) -> dict:
@ -47,6 +70,17 @@ def calculate_daily_stats(date_str: str = None):
# 1. 용량 정보 조회
capacities = get_plant_capacities(client)
# 발전소 정보 빌드 (하이브리드 크롤링용)
all_plants = get_all_plants()
plant_info_map = {}
for p in all_plants:
is_split = p.get('options', {}).get('is_split', False)
if is_split:
plant_info_map['nrems-01'] = p
plant_info_map['nrems-02'] = p
else:
plant_info_map[p.get('id', '')] = p
# 2. 해당일 로그 조회 (KST 날짜 범위를 UTC로 변환하여 쿼리)
kst = timezone(timedelta(hours=9))
start_kst = datetime.strptime(f"{date_str} 00:00:00", "%Y-%m-%d %H:%M:%S").replace(tzinfo=kst)
@ -82,6 +116,37 @@ def calculate_daily_stats(date_str: str = None):
# 최대 출력
peak_kw = group['current_kw'].max() if len(group) > 0 else 0
# 하이브리드 보정 로직 적용 (원 모니터링 사이트 통계 크롤링)
plant_info = plant_info_map.get(plant_id)
if plant_info:
plant_type = plant_info.get('type')
is_split = plant_info.get('options', {}).get('is_split', False)
history_crawler = get_history_crawler(plant_type)
if history_crawler:
try:
print(f" 📡 [{plant_id}] 원본 사이트 통계 크롤링 시도 ({date_str}) ...")
# fetch_history_daily는 리스트 반환: [{'plant_id': '...', 'date': '...', 'generation_kwh': ...}]
history_data = history_crawler(plant_info, date_str, date_str)
if history_data:
# nrems-01, nrems-02 분할 및 단일 매칭 처리
matched = [item for item in history_data if item.get('plant_id') == plant_id]
if not matched and len(history_data) == 1 and not is_split:
matched = history_data
if matched:
original_val = matched[0].get('generation_kwh', 0)
if original_val > 0:
print(f" ➔ 🟢 보정 성공: 기존 집계 {total_generation:.1f} kWh ➔ 원본 {original_val:.1f} kWh")
total_generation = original_val
else:
print(f" ➔ ⚠️ 원본 값이 0이므로 보정을 건너뜁니다.")
else:
print(f" ➔ ⚠️ 원본 데이터 중 {plant_id}와 일치하는 항목을 찾지 못했습니다.")
else:
print(f" ➔ ⚠️ 원본 데이터가 비어 있습니다.")
except Exception as ex:
print(f" ➔ ❌ 원본 사이트 크롤링 실패 (Fallback 기존 집계 적용): {ex}")
# 이용률 시간 = 발전량 / 용량
capacity = capacities.get(plant_id, 99.0)
generation_hours = round(total_generation / capacity, 2) if capacity > 0 else 0