12
12
import json
13
13
from urllib .parse import urlencode
14
14
from PIL import Image
15
+ import asyncio
16
+
17
+ from quartz_solar_forecast .pydantic_models import PVSite
18
+ from quartz_solar_forecast .forecasts import forecast_v1_tilt_orientation
19
+ from quartz_solar_forecast .forecast import predict_tryolabs
20
+ from quartz_solar_forecast .data import get_nwp , process_pv_data
21
+ from quartz_solar_forecast .inverters .enphase import process_enphase_data
22
+ from quartz_solar_forecast .inverters .solis import SolisData , get_solis_data
15
23
16
24
# Load environment variables
17
25
load_dotenv ()
23
31
# Add the parent directory to the Python path
24
32
sys .path .append (os .path .dirname (os .path .dirname (os .path .abspath (__file__ ))))
25
33
26
- from quartz_solar_forecast .pydantic_models import PVSite
27
- from quartz_solar_forecast .forecasts import forecast_v1_tilt_orientation
28
- from quartz_solar_forecast .forecast import predict_tryolabs
29
- from quartz_solar_forecast .data import get_nwp , process_pv_data
30
- from quartz_solar_forecast .inverters .enphase import process_enphase_data
31
-
32
34
# Get the directory of the current script
33
35
script_dir = os .path .dirname (os .path .abspath (__file__ ))
34
36
@@ -144,11 +146,14 @@ def make_pv_data(
144
146
ts : pd .Timestamp ,
145
147
access_token : str = None ,
146
148
enphase_system_id : str = None ,
149
+ solis_data : pd .DataFrame = None
147
150
) -> xr .Dataset :
148
151
live_generation_kw = None
149
152
150
153
if site .inverter_type == "enphase" and access_token and enphase_system_id :
151
154
live_generation_kw = get_enphase_data (enphase_system_id , access_token )
155
+ elif site .inverter_type == "solis" and solis_data is not None :
156
+ live_generation_kw = solis_data
152
157
153
158
da = process_pv_data (live_generation_kw , ts , site )
154
159
return da
@@ -160,6 +165,7 @@ def predict_ocf(
160
165
nwp_source : str = "icon" ,
161
166
access_token : str = None ,
162
167
enphase_system_id : str = None ,
168
+ solis_data : pd .DataFrame = None
163
169
):
164
170
if ts is None :
165
171
ts = pd .Timestamp .now ().round ("15min" )
@@ -168,7 +174,7 @@ def predict_ocf(
168
174
169
175
nwp_xr = get_nwp (site = site , ts = ts , nwp_source = nwp_source )
170
176
pv_xr = make_pv_data (
171
- site = site , ts = ts , access_token = access_token , enphase_system_id = enphase_system_id
177
+ site = site , ts = ts , access_token = access_token , enphase_system_id = enphase_system_id , solis_data = solis_data
172
178
)
173
179
174
180
pred_df = forecast_v1_tilt_orientation (nwp_source , nwp_xr , pv_xr , ts , model = model )
@@ -181,9 +187,10 @@ def run_forecast(
181
187
nwp_source : str = "icon" ,
182
188
access_token : str = None ,
183
189
enphase_system_id : str = None ,
190
+ solis_data : pd .DataFrame = None
184
191
) -> pd .DataFrame :
185
192
if model == "gb" :
186
- return predict_ocf (site , None , ts , nwp_source , access_token , enphase_system_id )
193
+ return predict_ocf (site , None , ts , nwp_source , access_token , enphase_system_id , solis_data )
187
194
elif model == "xgb" :
188
195
return predict_tryolabs (site , ts )
189
196
else :
@@ -192,7 +199,8 @@ def run_forecast(
192
199
def fetch_data_and_run_forecast (
193
200
site : PVSite ,
194
201
access_token : str = None ,
195
- enphase_system_id : str = None
202
+ enphase_system_id : str = None ,
203
+ solis_data : pd .DataFrame = None
196
204
):
197
205
with st .spinner ("Running forecast..." ):
198
206
try :
@@ -208,6 +216,7 @@ def fetch_data_and_run_forecast(
208
216
ts = ts ,
209
217
access_token = access_token ,
210
218
enphase_system_id = enphase_system_id ,
219
+ solis_data = solis_data
211
220
)
212
221
213
222
# Create a site without inverter for comparison
@@ -246,10 +255,11 @@ def fetch_data_and_run_forecast(
246
255
longitude = st .sidebar .number_input ("Longitude" , min_value = - 180.0 , max_value = 180.0 , value = - 1.25 , step = 0.01 )
247
256
capacity_kwp = st .sidebar .number_input ("Capacity (kWp)" , min_value = 0.1 , value = 1.25 , step = 0.01 )
248
257
249
- inverter_type = st .sidebar .selectbox ("Select Inverter" , ["No Inverter" , "Enphase" ])
258
+ inverter_type = st .sidebar .selectbox ("Select Inverter" , ["No Inverter" , "Enphase" , "Solis" ])
250
259
251
260
access_token = None
252
261
enphase_system_id = None
262
+ solis_data = None
253
263
254
264
if inverter_type == "Enphase" :
255
265
if "access_token" not in st .session_state :
@@ -258,6 +268,8 @@ def fetch_data_and_run_forecast(
258
268
access_token , enphase_system_id = st .session_state ["access_token" ], os .getenv (
259
269
"ENPHASE_SYSTEM_ID"
260
270
)
271
+ elif inverter_type == "Solis" :
272
+ solis_data = SolisData ()
261
273
262
274
if st .sidebar .button ("Run Forecast" ):
263
275
if inverter_type == "Enphase" and (access_token is None or enphase_system_id is None ):
@@ -270,12 +282,21 @@ def fetch_data_and_run_forecast(
270
282
latitude = latitude ,
271
283
longitude = longitude ,
272
284
capacity_kwp = capacity_kwp ,
273
- inverter_type = "enphase" if inverter_type == "Enphase" else "none" # Changed this line
285
+ inverter_type = inverter_type . lower ()
274
286
)
275
287
276
- predictions_df , ts = fetch_data_and_run_forecast (
277
- site , access_token , enphase_system_id
278
- )
288
+ # Fetch data based on the selected inverter type
289
+ if inverter_type == "Enphase" :
290
+ predictions_df , ts = fetch_data_and_run_forecast (
291
+ site , access_token , enphase_system_id
292
+ )
293
+ elif inverter_type == "Solis" :
294
+ solis_df = asyncio .run (get_solis_data ())
295
+ predictions_df , ts = fetch_data_and_run_forecast (
296
+ site , solis_data = solis_df
297
+ )
298
+ else :
299
+ predictions_df , ts = fetch_data_and_run_forecast (site )
279
300
280
301
if predictions_df is not None :
281
302
st .success ("Forecast completed successfully!" )
@@ -308,7 +329,7 @@ def fetch_data_and_run_forecast(
308
329
y = ["power_kw" , "power_kw_no_live_pv" ],
309
330
title = "Forecasted Power Generation Comparison" ,
310
331
labels = {
311
- "power_kw" : "Forecast with selected inverter type " ,
332
+ "power_kw" : f "Forecast with { inverter_type } " ,
312
333
"power_kw_no_live_pv" : "Forecast without recent PV data"
313
334
}
314
335
)
0 commit comments