From 9facc2d0c45da76e753ab937afbf1c4749bb0da0 Mon Sep 17 00:00:00 2001 From: Aryan Bhosale <36108149+aryanbhosale@users.noreply.github.com> Date: Mon, 15 Apr 2024 19:03:10 +0530 Subject: [PATCH] updated enphase api to v4 (#106) * updated api to v4 * added missing brackets * changed varnames * ocf_style coding * access token generator * removed the redundant import * example env format * authorization url format * added venv to gitignore --------- Co-authored-by: root --- .env.example | 7 +++- .gitignore | 1 + quartz_solar_forecast/data.py | 12 +++---- quartz_solar_forecast/inverters/enphase.py | 41 ++++++++++++++++++---- 4 files changed, 45 insertions(+), 16 deletions(-) diff --git a/.env.example b/.env.example index c0d3ee9d..4bc6e4ac 100644 --- a/.env.example +++ b/.env.example @@ -1,6 +1,11 @@ # User needs to add their Enphase API details + +ENPHASE_SYSTEM_ID = 'user_enphase_system_id' +ENPHASE_CLIENT_ID = 'user_enphase_client_id' +ENPHASE_CLIENT_SECRET = 'user_enphase_client_secret' ENPHASE_API_KEY = 'user_enphase_api_key' -ENPHASE_USER_ID = 'user_enphase_user_id' +# Replace ENPHASE_CLIENT_ID below with the actual client id +AUTHORIZATION_URL = 'https://api.enphaseenergy.com/oauth/authorize?response_type=code&client_id=ENPHASE_CLIENT_ID' # This section is for OpenMeteo setup diff --git a/.gitignore b/.gitignore index 03657a0e..af0b03cc 100644 --- a/.gitignore +++ b/.gitignore @@ -3,3 +3,4 @@ scripts/datapipes/UK_PV_metadata.csv scripts/datapipes/nwp_data quartz_solar_forecast/data .env +venv \ No newline at end of file diff --git a/quartz_solar_forecast/data.py b/quartz_solar_forecast/data.py index a2946748..d814dbf8 100644 --- a/quartz_solar_forecast/data.py +++ b/quartz_solar_forecast/data.py @@ -2,7 +2,7 @@ import json import ssl from datetime import datetime -import os # Add import for os module +import os import numpy as np import pandas as pd @@ -14,16 +14,13 @@ from retry_requests import retry from quartz_solar_forecast.pydantic_models import PVSite -from quartz_solar_forecast.inverters.enphase import get_enphase_data # Added import for get_enphase_data from /inverters/enphase.py +from quartz_solar_forecast.inverters.enphase import get_enphase_data ssl._create_default_https_context = ssl._create_unverified_context -# Load environment variables from .env file from dotenv import load_dotenv -# Assigning secrets from the .env file -ENPHASE_API_KEY = os.getenv('ENPHASE_API_KEY') -ENPHASE_USER_ID = os.getenv('ENPHASE_USER_ID') +ENPHASE_SYSTEM_ID = os.getenv('ENPHASE_SYSTEM_ID') def get_nwp(site: PVSite, ts: datetime, nwp_source: str = "icon") -> xr.Dataset: """ @@ -155,13 +152,12 @@ def make_pv_data(site: PVSite, ts: pd.Timestamp) -> xr.Dataset: :param ts: the timestamp of the site :return: The combined PV dataset in xarray form """ - # Check if the site has an inverter and use_enphase_data flag accordingly use_enphase_data = site.is_inverter if use_enphase_data: # Fetch live Enphase data and store it in live_generation_wh - live_generation_wh = get_enphase_data(ENPHASE_USER_ID, ENPHASE_API_KEY) + live_generation_wh = get_enphase_data(ENPHASE_SYSTEM_ID) else: live_generation_wh = np.nan # Default value if not using live Enphase data diff --git a/quartz_solar_forecast/inverters/enphase.py b/quartz_solar_forecast/inverters/enphase.py index dc25a687..37e7ebbe 100644 --- a/quartz_solar_forecast/inverters/enphase.py +++ b/quartz_solar_forecast/inverters/enphase.py @@ -1,20 +1,47 @@ import requests +import os -def get_enphase_data(enphase_user_id: str, enphase_api_key: str) -> float: +from dotenv import load_dotenv + +ENPHASE_CLIENT_ID = os.getenv('ENPHASE_CLIENT_ID') +ENPHASE_CLIENT_SECRET = os.getenv('ENPHASE_CLIENT_SECRET') +ENPHASE_API_KEY = os.getenv('ENPHASE_API_KEY') + +def get_enphase_access_token(): """ - Get live PV generation data from Enphase API + Obtain an access token for the Enphase API using the Client Credentials Grant flow. + """ + url = "https://api.enphaseenergy.com/oauth/token" + headers = { + "Content-Type": "application/x-www-form-urlencoded", + "Authorization": f"Basic {(ENPHASE_CLIENT_ID + ':' + ENPHASE_CLIENT_SECRET).encode().decode('utf-8')}", + } + data = { + "grant_type": "client_credentials", + "scope": "read" + } + + response = requests.post(url, headers=headers, data=data) + response.raise_for_status() + return response.json()["access_token"] - :param enphase_user_id: User ID for Enphase API - :param enphase_api_key: API Key for Enphase API +def get_enphase_data(enphase_system_id: str) -> float: + """ + Get live PV generation data from Enphase API v4 + + :param enphase_system_id: System ID for Enphase API :return: Live PV generation in Watt-hours, assumes to be a floating-point number """ - url = f'https://api.enphaseenergy.com/api/v2/systems/{enphase_user_id}/summary' - headers = {'Authorization': f'Bearer {enphase_api_key}'} + url = f'https://api.enphaseenergy.com/api/v4/{enphase_system_id}/summary' + headers = { + 'Authorization': f'Bearer {get_enphase_access_token()}', + 'key': ENPHASE_API_KEY + } response = requests.get(url, headers=headers) data = response.json() # Extracting live generation data assuming it's in Watt-hours live_generation_wh = data['current_power']['power'] - + return live_generation_wh \ No newline at end of file