The energy generation (in kWh) is required to be uploaded to make accurate forecasts (see example link). These data is stored on Meteo for Energy databases and also available for the user in case third party services require this information.
This example will show:
# First of all, import required packages
%matplotlib inline
import datetime
import requests
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
url_base = 'https://api.meteoforenergy.com/meteocast/v1'
# Authorization
headers = {}
headers['Authorization'] = 'Bearer eyJ...' # Required: Your site API key (JWT)
/usr/local/lib/python3.6/dist-packages/pandas/compat/_optional.py:124: UserWarning: Pandas requires version '1.2.1' or newer of 'bottleneck' (version '1.2.0' currently installed). warnings.warn(msg, UserWarning)
Now, we can start preparing our request of energy generation for a site.
time_unix (seconds since 00:00:00 UTC on 1 January 1970) datetime_iso8601 with UTC time zone in ISO-8601 formatdatetime_local as the datetime on site configuration defined local timevalue of generated energy in kWh# URL to use for the API request
url = url_base + '/ts/real/site'
# Time period that we will request
dateIni = datetime.datetime(2021,1,1)
dateFin = datetime.datetime(2021,1,31)
# Define required GET parameters for the request
params = {}
params['site_id'] = '98fkae' # Required: Site identification code
params['date_ini'] = dateIni.strftime('%Y-%m-%d') # Required: date_ini requires ISO-8601 format
params['date_fin'] = dateFin.strftime('%Y-%m-%d') # Required: date_fin requires ISO-8601 format
params['dph'] = 1 # Optional: Data Per Hour: 1=hourly (default), 4=15min, 6=10min
# Request to the API the data defined on the parameters
r = requests.get(url, params=params, headers=headers)
if( r.status_code == 200 ):
# Meta
site_name = r.json()['meta']['name']
# Data
df = pd.DataFrame(r.json()['data']) # or r.json().get('data')
print(df.head())
print(df.dtypes)
time_unix datetime_iso8601 datetime_local value 0 1609455600 2020-12-31T23:00:00.000Z 2021-01-01 00:00 0.0 1 1609459200 2021-01-01T00:00:00.000Z 2021-01-01 01:00 0.0 2 1609462800 2021-01-01T01:00:00.000Z 2021-01-01 02:00 0.0 3 1609466400 2021-01-01T02:00:00.000Z 2021-01-01 03:00 0.0 4 1609470000 2021-01-01T03:00:00.000Z 2021-01-01 04:00 0.0 time_unix int64 datetime_iso8601 object datetime_local object value float64 dtype: object
The response is a JSON that is converted to a DataFrame, but all the types are not correctly parsed (datetimes are objects).
So we need to define correctly the datetime columns and define it on our desired time zone (List of tz database time zones), as it is localized in UTC time zone.
# Convert type from object to datetime, and then localize
df['datetime_iso8601'] = pd.to_datetime(df['datetime_iso8601']) # datetime: object -> datetime64[ns, UTC]
df['datetime_iso8601'] = df['datetime_iso8601'].dt.tz_convert('Europe/Madrid') # datetime: datetime64[ns, UTC] -> datetime64[ns, Europe/Madrid]
print(df.head())
print(df.dtypes)
time_unix datetime_iso8601 datetime_local value 0 1609455600 2021-01-01 00:00:00+01:00 2021-01-01 00:00 0.0 1 1609459200 2021-01-01 01:00:00+01:00 2021-01-01 01:00 0.0 2 1609462800 2021-01-01 02:00:00+01:00 2021-01-01 02:00 0.0 3 1609466400 2021-01-01 03:00:00+01:00 2021-01-01 03:00 0.0 4 1609470000 2021-01-01 04:00:00+01:00 2021-01-01 04:00 0.0 time_unix int64 datetime_iso8601 datetime64[ns, Europe/Madrid] datetime_local object value float64 dtype: object
Similarly, we can also use Unix Epoch Time to make the same transformation
# datetime: Unix epoch time -> datetime64[ns, Europe/Madrid]
df['datetime_local'] = pd.to_datetime(df['time_unix'], unit='s').dt.tz_localize('UTC') \
.dt.tz_convert('Europe/Madrid')
print(df.head())
print(df.dtypes)
time_unix datetime_iso8601 datetime_local value 0 1609455600 2021-01-01 00:00:00+01:00 2021-01-01 00:00:00+01:00 0.0 1 1609459200 2021-01-01 01:00:00+01:00 2021-01-01 01:00:00+01:00 0.0 2 1609462800 2021-01-01 02:00:00+01:00 2021-01-01 02:00:00+01:00 0.0 3 1609466400 2021-01-01 03:00:00+01:00 2021-01-01 03:00:00+01:00 0.0 4 1609470000 2021-01-01 04:00:00+01:00 2021-01-01 04:00:00+01:00 0.0 time_unix int64 datetime_iso8601 datetime64[ns, Europe/Madrid] datetime_local datetime64[ns, Europe/Madrid] value float64 dtype: object
Note that we haven't use the response datetime_local directly as some timezones have Daylight Saving Time (DST) activated and some datetimes might repeat or not appear. To avoid raising errors, it's better to proceed as mentioned.
It's time to plot the information requested for data validation.
# Set `datetime` as index to show on X axis
fig = plt.figure(figsize=(14,6), dpi=80)
df = df.set_index('datetime_local')
#df['value'].plot()
OX = df.index + pd.Timedelta(minutes=30) # As values are hourly averages, we centre at XX:30
fig = plt.figure(figsize=(14,6), dpi=80)
plt.plot(OX, df['value'], c='#95c11f', marker='o',lw=2, label=u'Generation')
plt.title('Site %s real energy generation. %s - %s' % (site_name,
dateIni.strftime('%Y-%m-%d'),
dateFin.strftime('%Y-%m-%d')),
fontsize=24, fontweight='bold')
plt.xlabel('datetime', fontsize=16, fontweight='bold')
plt.ylabel('Energy [$kWh$]', fontsize=16, fontweight='bold')
plt.legend(loc='upper right')
plt.grid()
plt.show()
<Figure size 1120x480 with 0 Axes>