Skip to content

Commit

Permalink
Updates for v2.11.03
Browse files Browse the repository at this point in the history
  • Loading branch information
StefaE committed Dec 31, 2023
1 parent dadda81 commit 51ac375
Show file tree
Hide file tree
Showing 12 changed files with 93 additions and 64 deletions.
2 changes: 1 addition & 1 deletion PVForecast/__init__.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
__author__ = """Stefan E"""
__email__ = 'se_misc ... hotmail.com'
__version__ = '2.11.02'
__version__ = '2.11.03'
2 changes: 1 addition & 1 deletion PVForecast/csvinput.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,5 +47,5 @@ def getForecast_CSVInput(self, file):
return()

except Exception as e:
print("getForecast_CSVInput: " + str(e))
print("Error - getForecast_CSVInput: " + str(e))
sys.exit(1)
4 changes: 2 additions & 2 deletions PVForecast/dwdforecast.py
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ def getForecast_DWD_L(self):
self.csvName = re.sub(r'\.kml$', '.csv.gz', self.kmlName)

except Exception as e:
print ("getForecast_DWD_L: " + str(e))
print ("Warning - getForecast_DWD_L: " + str(e))

def getForecast_DWD_S(self):
"""Get newest MOSMIX_S forecast (global file), extract data for selected station;
Expand Down Expand Up @@ -155,7 +155,7 @@ def getForecast_DWD_S(self):
gzfile.close()

except Exception as e:
print ("getForecast_DWD_S: " + str(e))
print ("Warning - getForecast_DWD_S: " + str(e))


def readKML(self, file): # read forecast from .kml file --> self.kml as XML elementtree
Expand Down
30 changes: 15 additions & 15 deletions PVForecast/entsoe.py
Original file line number Diff line number Diff line change
Expand Up @@ -171,12 +171,12 @@ def _download_EntsoE(self):
df.drop(df.iloc[:, delCol], axis=1, inplace=True) # ... and drop them
colNames = [el[0] for el in df.columns] # now we have only 'Actual Aggregated' - drop that
df = df.set_axis(colNames, axis=1, copy=False)
df.fillna(method='ffill', inplace=True) # some zones have missing values for 'Actual Aggregated' if 'Acutal Consumption' > 0
df.fillna(method='bfill', inplace=True) # in case we have na in first row(s)
df.ffill(inplace=True) # some zones have missing values for 'Actual Aggregated' if 'Acutal Consumption' > 0
df.bfill(inplace=True) # in case we have na in first row(s)
if report == 'prices':
if zone.startswith('DE') or zone=='LU': _zone = 'DE_LU'
else: _zone = zone
_res = self.config['Entso-E'].get('resolution', '60T') # these two zones support 15m time interval for prices
_res = self.config['Entso-E'].get('resolution', '60T') # these two zones support 15m time interval for prices
df = self.client.query_day_ahead_prices(_zone, start=self._start, end=self._end, resolution = _res)

if df is not None:
Expand Down Expand Up @@ -217,7 +217,7 @@ def _download_EntsoE(self):
df = None
self._cols[zone][report] = None
if self._verbose > 0:
print('Warning EntsoE: Incomplete renewIntraday data found for zone ' + zone)
print('Warning Entso-E: Incomplete renewIntraday data found for zone ' + zone)

if df is not None:
earliest.append(df.index[0])
Expand All @@ -230,12 +230,12 @@ def _download_EntsoE(self):
except Exception as e:
err = str(e)
if err.startswith('503') or err.startswith('404'): # we have incomplete data for at least one zone/report
print('Warning EntsoE - Service unavailable ' + err[:3] + '), aborted')
print('Warning Entso-E - Service unavailable ' + err[:3] + '), aborted')
return False
elif self._verbose > 0:
if err == "":
err = "No data"
print('Error EntsoE ' + zone + " - " + report + ": " + err)
print('Error Entso-E ' + zone + " - " + report + ": " + err)

if self._entso[zone] is not None:
self._entso[zone] = self._entso[zone][self._entso[zone].index >= max(earliest)]
Expand Down Expand Up @@ -278,14 +278,14 @@ def _mapEmissionFactors(self):
url = 'https://github.com/electricitymaps/electricitymaps-contrib/raw/master/config/zones/' + yFName
req = requests.get(url)
if req.reason != 'OK':
print ('Warning EntsoE: Emission data download for ' + yFName + ' failed - ' + str(req.reason))
print ('Warning Entso-E: Emission data download for ' + yFName + ' failed - ' + str(req.reason))
else:
try:
with open(_file, 'w') as f: f.write(req.text) # write .yaml data to file, so that we have it next time
if self._verbose > 0:
print('Message EntsoE: downloaded emission factors for zone ' + myZone)
print('Message Entso-E: downloaded emission factors for zone ' + myZone)
except Exception as e:
print("Warning EntsoE: Emission data can't be written: " + yFName + ": "+ str(e))
print("Warning Entso-E: Emission data can't be written: " + yFName + ": "+ str(e))

try:
yFile = open(_file, 'r')
Expand All @@ -297,12 +297,12 @@ def _mapEmissionFactors(self):
elif isinstance(yEmission[emissionType], list): # list of past averages of electricityMap data over previous years
emissionFactors[emissionType] = yEmission[emissionType][-1]['value'] # use most recent one ...
else: # determine emission factor for each column; default factors as fall-back
print('Warning EntsoE: Zone ' + myZone + ' - unknown emission factor structure, using default for ' + emissionType)
print('Warning Entso-E: Zone ' + myZone + ' - unknown emission factor structure, using default for ' + emissionType)
except Exception as e:
print ('Warning EntsoE: File ' + yFName + ' error - using default emission factors: ' + str(e))
print ('Warning Entso-E: File ' + yFName + ' error - using default emission factors: ' + str(e))

else:
print('Warning EntsoE: Zone ' + zone + " - electricityMap doesn't have emission factors - using defaults")
print('Warning Entso-E: Zone ' + zone + " - electricityMap doesn't have emission factors - using defaults")

try:
emission_by_cols = [defaultEmissions[entso_to_emissions[(col[len('genActual')+1:])]] for col in cols['genActual']]
Expand Down Expand Up @@ -331,7 +331,7 @@ def _mapEmissionFactors(self):
entso.rename(columns = map, inplace=True)
# entso.to_csv(self.storePath + zone + "_" + self.IssueTime[:16].replace(' ', '_').replace(':', '-') + '_entso_short.csv.gz', compression='gzip') # -- for debugging
else:
print('Error EntsoE: Zone ' + zone + ' - no essential columns to keep')
print('Error Entso-E: Zone ' + zone + ' - no essential columns to keep')
entso = None
else:
for col in [c for c in entso.columns if c.startswith('calc')]:
Expand All @@ -341,10 +341,10 @@ def _mapEmissionFactors(self):
except Exception as e:
exception_traceback = sys.exc_info()[2]
if entso is not None:
print('Warning EntsoE (line ' + str(exception_traceback.tb_lineno) + '): Incomplete data for zone ' + zone + ': ' + str(e))
print('Warning Entso-E (line ' + str(exception_traceback.tb_lineno) + '): Incomplete data for zone ' + zone + ': ' + str(e))
entso.to_csv(self.storePath + zone + "_" + self.IssueTime[:16].replace(' ', '_').replace(':', '-') + '_entso_report_err.csv.gz', compression='gzip') # -- for debugging
else:
print('Warning EntsoE (line ' + str(exception_traceback.tb_lineno) + '): No data for zone ' + zone + ': ' + str(e))
print('Warning Entso-E (line ' + str(exception_traceback.tb_lineno) + '): No data for zone ' + zone + ': ' + str(e))
entso = None

self._entso[zone] = entso
Expand Down
27 changes: 19 additions & 8 deletions PVForecast/forecast_manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -278,6 +278,23 @@ def processFileInput(self):
sys.tracebacklimit=0
raise Exception("processFileInput: type '" + type + "' unsupported")
return()

def processMethod(self, m):
try:
print('processing ' + m)
if m == 'MOSMIX_L': self.processDWDFile('L') # gets latest forecast (MOSMIX_L - DWD)
elif m == 'MOSMIX_S': self.processDWDFile('S') # gets latest forecast (MOSMIX_S - DWD)
elif m == 'SolCast': self.processSolCast() # get / post solcast
elif m == 'VisualCrossing': self.processVisualCrossing() # get VisualCrossing data
elif m == 'OpenWeatherMap': self.processOpenWeather() # get OpenWeatherMap data
elif m == 'Entso-E': self.processEntsoE() # Entso-E based CO2 forecast
elif m == 'CO2signal': self.processCO2signal() # CO2signal from electricityMaps.com
elif m == 'FileInput': self.processFileInput() # process file input
except SystemExit as e:
print('Terminating in method ' + m + '; review config file to fix error, or report issue on Github')
sys.exit(1)
except Exception as e:
print('Error - Method ' + m + ': ' + str(e))

def runForecasts(self):
methods = ['MOSMIX_L', 'MOSMIX_S', 'SolCast', 'VisualCrossing', 'OpenWeatherMap', 'Entso-E', 'CO2signal', 'FileInput']
Expand All @@ -302,11 +319,5 @@ def runForecasts(self):
print("Error: no data providers selected in config file")
sys.exit(1)

if 'MOSMIX_L' in runList: self.processDWDFile('L') # gets latest forecast (MOSMIX_L - DWD)
if 'MOSMIX_S' in runList: self.processDWDFile('S') # gets latest forecast (MOSMIX_S - DWD)
if 'SolCast' in runList: self.processSolCast() # get / post solcast
if 'VisualCrossing' in runList: self.processVisualCrossing() # get VisualCrossing data
if 'OpenWeatherMap' in runList: self.processOpenWeather() # get OpenWeatherMap data
if 'Entso-E' in runList: self.processEntsoE() # Entso-E based CO2 forecast
if 'CO2signal' in runList: self.processCO2signal() # CO2signal from electricityMaps.com
if 'FileInput' in runList: self.processFileInput() # process file input
for m in runList:
self.processMethod(m)
27 changes: 14 additions & 13 deletions PVForecast/influx.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,15 +43,17 @@ def __init__(self, config):
if 'Influx' not in self.config.sections():
sys.tracebacklimit=0
raise Exception("missing section 'Influx' in config file")
self._host = self.config['Influx'].get('host', 'localhost')
self._port = self.config['Influx'].getint('port', 8086)
self._database = self.config['Influx'].get('database', None)
self._retention = self.config['Influx'].get('retention', None) # retention policy (only for Influx v1.x)
self._username = self.config['Influx'].get('username', 'root')
self._password = self.config['Influx'].get('password', 'root')
self._token = self.config['Influx'].get('token', None)
self._org = self.config['Influx'].get('org', None)
self._influx_V2 = self.config['Influx'].getboolean('influx_v2', False)
self._host = self.config['Influx'].get('host', 'localhost')
self._posthost = self.config['Influx'].get('post_host', self._host)
self._port = self.config['Influx'].getint('port', 8086)
self._database = self.config['Influx'].get('database', None)
self._postdatabase = self.config['Influx'].get('post_database', self._database)
self._retention = self.config['Influx'].get('retention', None) # retention policy (only for Influx v1.x)
self._username = self.config['Influx'].get('username', 'root')
self._password = self.config['Influx'].get('password', 'root')
self._token = self.config['Influx'].get('token', None)
self._org = self.config['Influx'].get('org', None)
self._influx_V2 = self.config['Influx'].getboolean('influx_v2', False)
try:
if self._influx_V2:
if self._database is None: self._database = self.config['Influx'].get('bucket')
Expand Down Expand Up @@ -165,7 +167,7 @@ def getData(self, start, table):
return history

except Exception as e:
print("getData: " + str(e))
print("Warning - getData: " + str(e))
return pd.DataFrame()

def _verifyDB(self, client):
Expand Down Expand Up @@ -198,8 +200,7 @@ def getPostData(self, solcast, power_field):

meas, field = self.config['Influx'].get(power_field).split('.')

# client = InfluxDBClient(host=self._host, port=self._port, database=self._database, username=self._username, password=self._password)
client = InfluxDBClient(host='solaranzeige', port=self._port, database='solaranzeige', username=self._username, password=self._password) # <=================================
client = InfluxDBClient(host=self._posthost, port=self._port, database=self._postdatabase, username=self._username, password=self._password)
sql = 'SELECT mean("' + field +'") AS "total_power" FROM "' + meas + '" WHERE time >= ' + "'" + startTime + "' AND time < '" + endTime + "' GROUP BY time(5m)"
select = client.query(sql)
postDict = []
Expand All @@ -219,5 +220,5 @@ def getPostData(self, solcast, power_field):
else: postDict = None
return(postDict)
except Exception as e:
print("getPostData: " + str(e))
print("Warning - getPostData: " + str(e))
return(None)
6 changes: 3 additions & 3 deletions PVForecast/pvmodel.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,8 +54,8 @@ def __init__(self, config, section = 'PVSystem'):
try:
warnings.filterwarnings("ignore", category=RuntimeWarning, message=".*overflow.*")
self._pvversion = pvlib.__version__
if version.parse(self._pvversion) > version.parse('0.10.1'):
print("Warning --- pvmodel not tested with pvlib > 0.10.1")
if version.parse(self._pvversion) > version.parse('0.10.3'):
print("Warning --- pvmodel not tested with pvlib > 0.10.3")
elif version.parse(self._pvversion) < version.parse('0.9.0'):
sys.tracebacklimit=0
raise Exception("ERROR --- require pvlib >= 0.9.0")
Expand Down Expand Up @@ -217,7 +217,7 @@ def getIrradiance(self, weather: Forecast, model='disc'):
sys.tracebacklimit=0
raise Exception("ERROR --- incorrect irradiance model called: " + model)
except Exception as e:
print("getIrradiance: " + str(e))
print("Error - getIrradiance: " + str(e))
sys.exit(1)

if (model != 'clearsky' and model != 'clearsky_scaling' and model != 'campbell_norman'):
Expand Down
Loading

0 comments on commit 51ac375

Please sign in to comment.