#!/usr/bin/env python # -*- coding: utf-8 -*- """ 데이터 검증 스크립트 각 발전소별로 특정 날짜/월/연도의 실제 데이터를 조회하여 검증 """ from datetime import datetime from crawlers import nrems, hyundai, kremc, sun_wms, cmsolar from config import SYSTEM_CONSTANTS def format_hourly_data(data, date_str, plant_name): """시간별 데이터 포맷팅""" print(f"\n{'='*80}") print(f"[{plant_name}] 시간별 데이터: {date_str}") print(f"{'='*80}") if not data: print(" ❌ 데이터 없음") return # 시간별로 그룹화 hourly_dict = {} for record in data: timestamp = record.get('timestamp', '') if timestamp.startswith(date_str): hour = timestamp.split(' ')[1][:2] if ' ' in timestamp else '00' kwh = record.get('generation_kwh', 0) if hour not in hourly_dict: hourly_dict[hour] = 0 hourly_dict[hour] += kwh if not hourly_dict: print(" ❌ 해당 날짜 데이터 없음") return print(f" 총 {len(hourly_dict)}시간 데이터") print(f"\n {'시간':<8} {'발전량(kWh)':<15}") print(f" {'-'*25}") total = 0 for hour in sorted(hourly_dict.keys()): kwh = hourly_dict[hour] total += kwh print(f" {hour}:00 {kwh:>10.2f}") print(f" {'-'*25}") print(f" {'합계':<8} {total:>10.2f}") def format_daily_data(data, year_month, plant_name): """일별 데이터 포맷팅""" print(f"\n{'='*80}") print(f"[{plant_name}] 일별 데이터: {year_month}") print(f"{'='*80}") if not data: print(" ❌ 데이터 없음") return # 해당 월의 데이터만 필터링 monthly_data = [d for d in data if d.get('date', '').startswith(year_month)] if not monthly_data: print(" ❌ 해당 월 데이터 없음") return print(f" 총 {len(monthly_data)}일 데이터") print(f"\n {'날짜':<15} {'발전량(kWh)':<15}") print(f" {'-'*30}") total = 0 for record in sorted(monthly_data, key=lambda x: x.get('date', '')): date = record.get('date', '') kwh = record.get('generation_kwh', 0) total += kwh print(f" {date:<15} {kwh:>10.2f}") print(f" {'-'*30}") print(f" {'합계':<15} {total:>10.2f}") def format_monthly_data(data, year, plant_name): """월별 데이터 포맷팅""" print(f"\n{'='*80}") print(f"[{plant_name}] 월별 데이터: {year}년") print(f"{'='*80}") if not data: print(" ❌ 데이터 없음") return # 해당 연도의 데이터만 필터링 yearly_data = [d for d in data if d.get('month', '').startswith(year)] if not yearly_data: print(" ❌ 해당 연도 데이터 없음") return print(f" 총 {len(yearly_data)}개월 데이터") print(f"\n {'월':<10} {'발전량(kWh)':<15}") print(f" {'-'*25}") total = 0 for record in sorted(yearly_data, key=lambda x: x.get('month', '')): month = record.get('month', '') kwh = record.get('generation_kwh', 0) total += kwh print(f" {month:<10} {kwh:>10.2f}") print(f" {'-'*25}") print(f" {'합계':<10} {total:>10.2f}") if len(yearly_data) > 0: print(f" {'평균':<10} {total/len(yearly_data):>10.2f}") def verify_plant(plant_config, crawler_module): """개별 발전소 데이터 검증""" plant_name = plant_config['name'] print(f"\n{'#'*80}") print(f"# {plant_name}") print(f"{'#'*80}") try: # 1. 시간별 데이터: 2025-05-10, 2024-10-20 print(f"\n[1/6] 시간별 데이터 수집 중...") hourly_2025 = crawler_module.fetch_history_hourly(plant_config, '2025-05-10', '2025-05-10') format_hourly_data(hourly_2025, '2025-05-10', plant_name) hourly_2024 = crawler_module.fetch_history_hourly(plant_config, '2024-10-20', '2024-10-20') format_hourly_data(hourly_2024, '2024-10-20', plant_name) # 2. 일별 데이터: 2025-05, 2024-07 print(f"\n[2/6] 일별 데이터 수집 중...") daily_2025 = crawler_module.fetch_history_daily(plant_config, '2025-05-01', '2025-05-31') format_daily_data(daily_2025, '2025-05', plant_name) daily_2024 = crawler_module.fetch_history_daily(plant_config, '2024-07-01', '2024-07-31') format_daily_data(daily_2024, '2024-07', plant_name) # 3. 월별 데이터: 2024년, 2025년 print(f"\n[3/6] 월별 데이터 수집 중...") monthly_2025 = crawler_module.fetch_history_monthly(plant_config, '2025-01', '2025-12') format_monthly_data(monthly_2025, '2025', plant_name) monthly_2024 = crawler_module.fetch_history_monthly(plant_config, '2024-01', '2024-12') format_monthly_data(monthly_2024, '2024', plant_name) print(f"\n>>> {plant_name} 검증 완료") except Exception as e: print(f"\n ❌ 오류 발생: {str(e)}") import traceback traceback.print_exc() def main(): """메인 함수""" print("\n" + "="*80) print(">>> 발전소 데이터 검증 스크립트 <<<") print("="*80) print(f"검증 일시: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}") print("\n[검증 대상]") print(" - 시간별: 2025-05-10, 2024-10-20") print(" - 일별: 2025년 5월, 2024년 7월") print(" - 월별: 2025년, 2024년") # 테스트 대상 발전소 설정 test_plants = [ # NREMS 1,2호기 (분리) ({'id': 'nrems-01', 'name': '1호기', 'type': 'nrems', 'auth': {'pscode': 'duce2023072288'}, 'options': {'is_split': True, 'unit_id': 1}, 'system': SYSTEM_CONSTANTS['nrems']}, nrems), ({'id': 'nrems-02', 'name': '2호기', 'type': 'nrems', 'auth': {'pscode': 'duce2023072288'}, 'options': {'is_split': True, 'unit_id': 2}, 'system': SYSTEM_CONSTANTS['nrems']}, nrems), # NREMS 3호기 ({'id': 'nrems-03', 'name': '3호기', 'type': 'nrems', 'auth': {'pscode': 'dc2023121086'}, 'options': {}, 'system': SYSTEM_CONSTANTS['nrems']}, nrems), # NREMS 4호기 ({'id': 'nrems-04', 'name': '4호기', 'type': 'nrems', 'auth': {'pscode': 'duce2023072269'}, 'options': {}, 'system': SYSTEM_CONSTANTS['nrems']}, nrems), # NREMS 9호기 ({'id': 'nrems-09', 'name': '9호기', 'type': 'nrems', 'auth': {'pscode': 'a2020061008'}, 'options': {}, 'system': SYSTEM_CONSTANTS['nrems']}, nrems), # KREMC 5호기 ({'id': 'kremc-05', 'name': '5호기', 'type': 'kremc', 'auth': {'user_id': '서대문도서관', 'password': 'sunhope5!'}, 'options': {'cid': '10013000376', 'cityProvCode': '11', 'rgnCode': '11410', 'dongCode': '1141011700', 'enso_type_code': '15001'}, 'system': SYSTEM_CONSTANTS['kremc']}, kremc), # Sun-WMS 6호기 ({'id': 'sunwms-06', 'name': '6호기', 'type': 'sun_wms', 'auth': {'payload_id': 'kc0fXUW0LUm2wZa+2NQI0Q==', 'payload_pw': 'PGXjU6ib2mKYwtrh2i3fIQ=='}, 'options': {}, 'system': SYSTEM_CONSTANTS['sun_wms']}, sun_wms), # Hyundai 8호기 ({'id': 'hyundai-08', 'name': '8호기', 'type': 'hyundai', 'auth': {'user_id': 'epecoop', 'password': 'sunhope0419', 'site_id': 'M0494'}, 'options': {}, 'system': SYSTEM_CONSTANTS['hyundai']}, hyundai), # CMSolar 10호기 ({'id': 'cmsolar-10', 'name': '10호기', 'type': 'cmsolar', 'auth': {'login_id': 'smart3131', 'password': 'ehdrb!123', 'site_no': '834'}, 'options': {}, 'system': SYSTEM_CONSTANTS['cmsolar']}, cmsolar), ] # 각 발전소 검증 for plant_config, crawler_module in test_plants: try: verify_plant(plant_config, crawler_module) except KeyboardInterrupt: print("\n\n⚠️ 사용자 중단") break except Exception as e: print(f"\n❌ {plant_config['name']} 검증 실패: {str(e)}") import traceback traceback.print_exc() continue print("\n" + "="*80) print(">>> 데이터 검증 완료 <<<") print("="*80) if __name__ == '__main__': main()