Skip to content
This repository was archived by the owner on Aug 14, 2026. It is now read-only.

Commit 3612bee

Browse files
committed
some improvements
1 parent 800b0a9 commit 3612bee

6 files changed

Lines changed: 178 additions & 137 deletions

File tree

‎app.py‎

Lines changed: 13 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -106,20 +106,14 @@ def init_weather_client():
106106
logger.warning("Weather API key not configured - weather feature disabled")
107107
return
108108

109-
latitude = weather_config.get("latitude")
110-
longitude = weather_config.get("longitude")
111-
112-
if latitude is None or longitude is None:
113-
logger.warning("Weather location not configured - weather feature disabled")
114-
return
115-
116109
city_name = weather_config.get("city_name", "")
110+
if not city_name:
111+
logger.warning("Weather city not configured - weather feature disabled")
112+
return
117113

118114
weather_client = WeatherClient(
119115
api_key=api_key,
120-
latitude=latitude,
121-
longitude=longitude,
122-
city_name=city_name if city_name else None
116+
city_name=city_name
123117
)
124118

125119
bad_conditions = weather_config.get("bad_weather_conditions", ["Rain", "Thunderstorm", "Drizzle", "Snow"])
@@ -130,7 +124,7 @@ def init_weather_client():
130124
min_cloud_cover=min_cloud_cover
131125
)
132126

133-
location_str = city_name if city_name else f"({latitude}, {longitude})"
127+
location_str = city_name
134128
logger.info(f"Weather client initialised for {location_str}")
135129

136130

@@ -182,8 +176,8 @@ def should_skip_discharge_for_weather() -> tuple:
182176
if not forecast:
183177
return False, "Weather data unavailable"
184178

185-
threshold_days = weather_config.get("bad_weather_threshold_days", 2)
186-
return weather_analyser.should_skip_discharge(forecast, threshold_days)
179+
min_solar_kwh = weather_config.get("min_solar_threshold_kwh", 0)
180+
return weather_analyser.should_skip_discharge(forecast, min_solar_kwh)
187181

188182

189183
def is_within_discharge_window() -> bool:
@@ -538,7 +532,7 @@ def complete_setup():
538532
if "weather" not in config:
539533
config["weather"] = {}
540534

541-
for key in ["enabled", "api_key", "city_name", "latitude", "longitude",
535+
for key in ["enabled", "api_key", "city_name",
542536
"inverter_capacity_kw", "panel_capacity_kw"]:
543537
if key in weather_data:
544538
config["weather"][key] = weather_data[key]
@@ -584,7 +578,7 @@ def get_status():
584578
"enabled": weather_config.get("enabled", False),
585579
"skip_active": current_state.get("weather_skip_active", False),
586580
"skip_reason": current_state.get("weather_skip_reason"),
587-
"threshold_days": weather_config.get("bad_weather_threshold_days", 2)
581+
"min_solar_threshold_kwh": weather_config.get("min_solar_threshold_kwh", 0)
588582
}
589583

590584
# Include free energy status
@@ -778,7 +772,7 @@ def get_weather():
778772
"forecast": forecast,
779773
"skip_discharge": skip_active,
780774
"skip_reason": skip_reason,
781-
"threshold_days": weather_config.get("bad_weather_threshold_days", 2),
775+
"min_solar_threshold_kwh": weather_config.get("min_solar_threshold_kwh", 0),
782776
"last_update": weather_forecast_cache.get("last_update").isoformat() if weather_forecast_cache.get("last_update") else None
783777
})
784778

@@ -790,9 +784,7 @@ def get_weather_config():
790784
return jsonify({
791785
"enabled": weather_config.get("enabled", False),
792786
"city_name": weather_config.get("city_name", ""),
793-
"latitude": weather_config.get("latitude"),
794-
"longitude": weather_config.get("longitude"),
795-
"bad_weather_threshold_days": weather_config.get("bad_weather_threshold_days", 2),
787+
"min_solar_threshold_kwh": weather_config.get("min_solar_threshold_kwh", 0),
796788
"bad_weather_conditions": weather_config.get("bad_weather_conditions", []),
797789
"min_cloud_cover_percent": weather_config.get("min_cloud_cover_percent", 70),
798790
"inverter_capacity_kw": weather_config.get("inverter_capacity_kw", 0),
@@ -836,12 +828,8 @@ def update_weather_config():
836828
config["weather"]["enabled"] = body["enabled"]
837829
if "city_name" in body:
838830
config["weather"]["city_name"] = body["city_name"]
839-
if "latitude" in body:
840-
config["weather"]["latitude"] = body["latitude"]
841-
if "longitude" in body:
842-
config["weather"]["longitude"] = body["longitude"]
843-
if "bad_weather_threshold_days" in body:
844-
config["weather"]["bad_weather_threshold_days"] = body["bad_weather_threshold_days"]
831+
if "min_solar_threshold_kwh" in body:
832+
config["weather"]["min_solar_threshold_kwh"] = body["min_solar_threshold_kwh"]
845833
if "bad_weather_conditions" in body:
846834
config["weather"]["bad_weather_conditions"] = body["bad_weather_conditions"]
847835
if "min_cloud_cover_percent" in body:

‎templates/index.html‎

Lines changed: 5 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -742,14 +742,13 @@ <h2>
742742
<div class="setting-item" style="flex: 2; position: relative;">
743743
<label>City</label>
744744
<input type="text" id="weatherCity" placeholder="Search city..." autocomplete="off">
745-
<input type="hidden" id="weatherLat">
746-
<input type="hidden" id="weatherLon">
747745
<input type="hidden" id="weatherCityName">
748746
<div id="cityDropdown" class="city-dropdown"></div>
749747
</div>
750748
<div class="setting-item">
751-
<label>Bad Days Threshold</label>
752-
<input type="number" id="weatherThreshold" min="1" max="7" value="2">
749+
<label>Min Solar Threshold (kWh)</label>
750+
<input type="number" id="weatherSolarThreshold" min="0" max="50" step="0.5" value="0">
751+
<small style="color: #666; font-size: 0.8em;">Skip discharge if tomorrow's forecast is below this</small>
753752
</div>
754753
<div class="setting-item">
755754
<label>Cloud Cover %</label>
@@ -1282,11 +1281,9 @@ <h2>Settings</h2>
12821281
const config = await response.json();
12831282

12841283
document.getElementById('weatherEnabled').checked = config.enabled;
1285-
document.getElementById('weatherLat').value = config.latitude || '';
1286-
document.getElementById('weatherLon').value = config.longitude || '';
12871284
document.getElementById('weatherCityName').value = config.city_name || '';
12881285
document.getElementById('weatherCity').value = config.city_name || '';
1289-
document.getElementById('weatherThreshold').value = config.bad_weather_threshold_days || 2;
1286+
document.getElementById('weatherSolarThreshold').value = config.min_solar_threshold_kwh || 0;
12901287
document.getElementById('weatherCloudCover').value = config.min_cloud_cover_percent || 70;
12911288
document.getElementById('weatherInverterCapacity').value = config.inverter_capacity_kw || 0;
12921289
document.getElementById('weatherPanelCapacity').value = config.panel_capacity_kw || 0;
@@ -1330,8 +1327,6 @@ <h2>Settings</h2>
13301327

13311328
document.getElementById('cityDropdown').addEventListener('click', (e) => {
13321329
if (e.target.classList.contains('city-option')) {
1333-
document.getElementById('weatherLat').value = e.target.dataset.lat;
1334-
document.getElementById('weatherLon').value = e.target.dataset.lon;
13351330
document.getElementById('weatherCityName').value = e.target.dataset.name;
13361331
document.getElementById('weatherCity').value = e.target.dataset.name;
13371332
document.getElementById('cityDropdown').classList.remove('show');
@@ -1358,9 +1353,7 @@ <h2>Settings</h2>
13581353
const payload = {
13591354
enabled: document.getElementById('weatherEnabled').checked,
13601355
city_name: document.getElementById('weatherCityName').value || '',
1361-
latitude: parseFloat(document.getElementById('weatherLat').value) || null,
1362-
longitude: parseFloat(document.getElementById('weatherLon').value) || null,
1363-
bad_weather_threshold_days: parseInt(document.getElementById('weatherThreshold').value) || 2,
1356+
min_solar_threshold_kwh: parseFloat(document.getElementById('weatherSolarThreshold').value) || 0,
13641357
min_cloud_cover_percent: parseInt(document.getElementById('weatherCloudCover').value) || 70,
13651358
inverter_capacity_kw: parseFloat(document.getElementById('weatherInverterCapacity').value) || 0,
13661359
panel_capacity_kw: parseFloat(document.getElementById('weatherPanelCapacity').value) || 0

‎tests/conftest.py‎

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,9 @@ def sample_weather_config():
1313
return {
1414
"enabled": True,
1515
"api_key": "test_api_key",
16-
"latitude": -33.8688,
17-
"longitude": 151.2093,
18-
"bad_weather_threshold_days": 2,
16+
"city_name": "Sydney, AU",
17+
"min_solar_threshold_kwh": 5.0,
18+
"panel_capacity_kw": 6.6,
1919
"bad_weather_conditions": ["Rain", "Thunderstorm", "Drizzle", "Snow"],
2020
"min_cloud_cover_percent": 70
2121
}

‎tests/test_app.py‎

Lines changed: 11 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -43,9 +43,9 @@ def app_client(self):
4343
"weather": {
4444
"enabled": True,
4545
"api_key": "test_key",
46-
"latitude": -33.8688,
47-
"longitude": 151.2093,
48-
"bad_weather_threshold_days": 2,
46+
"city_name": "Sydney, AU",
47+
"min_solar_threshold_kwh": 5.0,
48+
"panel_capacity_kw": 6.6,
4949
"bad_weather_conditions": ["Rain", "Thunderstorm"],
5050
"min_cloud_cover_percent": 70
5151
}
@@ -112,9 +112,8 @@ def test_weather_config_api(self, app_client):
112112

113113
assert response.status_code == 200
114114
assert data["enabled"] is True
115-
assert data["latitude"] == -33.8688
116-
assert data["longitude"] == 151.2093
117-
assert data["bad_weather_threshold_days"] == 2
115+
assert data["city_name"] == "Sydney, AU"
116+
assert data["min_solar_threshold_kwh"] == 5.0
118117
assert "api_key" not in data
119118
assert data["api_key_configured"] is True
120119

@@ -127,9 +126,8 @@ def test_weather_config_update(self, mock_init, mock_save, app_client):
127126
response = client.post('/api/weather/config',
128127
data=json.dumps({
129128
"enabled": False,
130-
"latitude": -34.0,
131-
"longitude": 152.0,
132-
"bad_weather_threshold_days": 3
129+
"city_name": "Melbourne, AU",
130+
"min_solar_threshold_kwh": 8.0
133131
}),
134132
content_type='application/json'
135133
)
@@ -214,8 +212,7 @@ def test_init_success(self, mock_analyzer, mock_client):
214212
"weather": {
215213
"enabled": True,
216214
"api_key": "valid_key",
217-
"latitude": -33.8688,
218-
"longitude": 151.2093,
215+
"city_name": "Sydney, AU",
219216
"bad_weather_conditions": ["Rain"],
220217
"min_cloud_cover_percent": 70
221218
}
@@ -227,8 +224,7 @@ def test_init_success(self, mock_analyzer, mock_client):
227224

228225
mock_client.assert_called_once_with(
229226
api_key="valid_key",
230-
latitude=-33.8688,
231-
longitude=151.2093
227+
city_name="Sydney, AU"
232228
)
233229
mock_analyzer.assert_called_once()
234230

@@ -266,7 +262,7 @@ def test_skip_no_forecast(self, mock_forecast):
266262

267263
with patch('app.DeyeCloudClient'):
268264
import app as app_module
269-
app_module.config = {"weather": {"enabled": True, "bad_weather_threshold_days": 2}}
265+
app_module.config = {"weather": {"enabled": True, "min_solar_threshold_kwh": 5.0}}
270266
app_module.weather_client = Mock()
271267
app_module.weather_analyser = Mock()
272268

@@ -285,7 +281,7 @@ def test_skip_bad_weather(self, mock_forecast):
285281

286282
with patch('app.DeyeCloudClient'):
287283
import app as app_module
288-
app_module.config = {"weather": {"enabled": True, "bad_weather_threshold_days": 2}}
284+
app_module.config = {"weather": {"enabled": True, "min_solar_threshold_kwh": 5.0}}
289285
app_module.weather_client = Mock()
290286
app_module.weather_analyser = Mock()
291287
app_module.weather_analyser.should_skip_discharge.return_value = (True, "3 bad days")

0 commit comments

Comments
 (0)