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/Meteo_PV/v1'
headers = {}
headers['X-Auth-Token-Site'] = '6e1dad336510539b32143b5eff0f8733'
headers['X-Auth-Token-User'] = '4cd6cf8de97bf10859302d5441c65143'
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 + '/real/ts/'
# Time period that we will request
dateIni = datetime.datetime(2020,1,1)
dateFin = datetime.datetime(2020,1,31)
# Define required GET parameters for the request
dict_Meteo = {}
dict_Meteo['date_ini'] = dateIni.strftime('%Y-%m-%d') # Required: date_ini requires ISO-8601 format
dict_Meteo['date_fin'] = dateFin.strftime('%Y-%m-%d') # Required: date_fin requires ISO-8601 format
dict_Meteo['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=dict_Meteo, headers=headers)
if( r.status_code == 200 ):
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 1577833200 2019-12-31T23:00:00.000Z 2020-01-01 00:00 0.0 1 1577836800 2020-01-01T00:00:00.000Z 2020-01-01 01:00 0.0 2 1577840400 2020-01-01T01:00:00.000Z 2020-01-01 02:00 0.0 3 1577844000 2020-01-01T02:00:00.000Z 2020-01-01 03:00 0.0 4 1577847600 2020-01-01T03:00:00.000Z 2020-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 1577833200 2020-01-01 00:00:00+01:00 2020-01-01 00:00 0.0 1 1577836800 2020-01-01 01:00:00+01:00 2020-01-01 01:00 0.0 2 1577840400 2020-01-01 02:00:00+01:00 2020-01-01 02:00 0.0 3 1577844000 2020-01-01 03:00:00+01:00 2020-01-01 03:00 0.0 4 1577847600 2020-01-01 04:00:00+01:00 2020-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 1577833200 2020-01-01 00:00:00+01:00 2020-01-01 00:00:00+01:00 0.0 1 1577836800 2020-01-01 01:00:00+01:00 2020-01-01 01:00:00+01:00 0.0 2 1577840400 2020-01-01 02:00:00+01:00 2020-01-01 02:00:00+01:00 0.0 3 1577844000 2020-01-01 03:00:00+01:00 2020-01-01 03:00:00+01:00 0.0 4 1577847600 2020-01-01 04:00:00+01:00 2020-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 real energy generation. %s - %s' % (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>