diff --git a/docs/_generated/configexample.md b/docs/_generated/configexample.md index 374b97b..c0d8a1b 100644 --- a/docs/_generated/configexample.md +++ b/docs/_generated/configexample.md @@ -136,7 +136,7 @@ } }, "general": { - "version": "0.2.0.dev70048701", + "version": "0.2.0.dev81043823", "data_folder_path": null, "data_output_subpath": "output", "latitude": 52.52, diff --git a/docs/_generated/configgeneral.md b/docs/_generated/configgeneral.md index 6ae8eaf..20dfe15 100644 --- a/docs/_generated/configgeneral.md +++ b/docs/_generated/configgeneral.md @@ -16,7 +16,7 @@ | latitude | `EOS_GENERAL__LATITUDE` | `Optional[float]` | `rw` | `52.52` | Latitude in decimal degrees between -90 and 90. North is positive (ISO 19115) (°) | | longitude | `EOS_GENERAL__LONGITUDE` | `Optional[float]` | `rw` | `13.405` | Longitude in decimal degrees within -180 to 180 (°) | | timezone | | `Optional[str]` | `ro` | `N/A` | Computed timezone based on latitude and longitude. | -| version | `EOS_GENERAL__VERSION` | `str` | `rw` | `0.2.0.dev70048701` | Configuration file version. Used to check compatibility. | +| version | `EOS_GENERAL__VERSION` | `str` | `rw` | `0.2.0.dev81043823` | Configuration file version. Used to check compatibility. | ::: @@ -28,7 +28,7 @@ ```json { "general": { - "version": "0.2.0.dev70048701", + "version": "0.2.0.dev81043823", "data_folder_path": null, "data_output_subpath": "output", "latitude": 52.52, @@ -46,7 +46,7 @@ ```json { "general": { - "version": "0.2.0.dev70048701", + "version": "0.2.0.dev81043823", "data_folder_path": null, "data_output_subpath": "output", "latitude": 52.52, diff --git a/docs/_generated/openapi.md b/docs/_generated/openapi.md index 0dde373..8a5aa4c 100644 --- a/docs/_generated/openapi.md +++ b/docs/_generated/openapi.md @@ -1,6 +1,6 @@ # Akkudoktor-EOS -**Version**: `v0.2.0.dev70048701` +**Version**: `v0.2.0.dev81043823` **Description**: This project provides a comprehensive solution for simulating and optimizing an energy system based on renewable energy sources. With a focus on photovoltaic (PV) systems, battery storage (batteries), load management (consumer requirements), heat pumps, electric vehicles, and consideration of electricity price data, this system enables forecasting and optimization of energy flow and costs over a specified period. diff --git a/openapi.json b/openapi.json index 5f76e22..37b81cf 100644 --- a/openapi.json +++ b/openapi.json @@ -3,7 +3,7 @@ "info": { "title": "Akkudoktor-EOS", "description": "This project provides a comprehensive solution for simulating and optimizing an energy system based on renewable energy sources. With a focus on photovoltaic (PV) systems, battery storage (batteries), load management (consumer requirements), heat pumps, electric vehicles, and consideration of electricity price data, this system enables forecasting and optimization of energy flow and costs over a specified period.", - "version": "v0.2.0.dev70048701" + "version": "v0.2.0.dev81043823" }, "paths": { "/v1/admin/cache/clear": { @@ -2525,7 +2525,7 @@ "general": { "$ref": "#/components/schemas/GeneralSettings-Output", "default": { - "version": "0.2.0.dev70048701", + "version": "0.2.0.dev81043823", "data_output_subpath": "output", "latitude": 52.52, "longitude": 13.405, @@ -4272,7 +4272,7 @@ "type": "string", "title": "Version", "description": "Configuration file version. Used to check compatibility.", - "default": "0.2.0.dev70048701" + "default": "0.2.0.dev81043823" }, "data_folder_path": { "anyOf": [ @@ -4346,7 +4346,7 @@ "type": "string", "title": "Version", "description": "Configuration file version. Used to check compatibility.", - "default": "0.2.0.dev70048701" + "default": "0.2.0.dev81043823" }, "data_folder_path": { "anyOf": [ diff --git a/src/akkudoktoreos/measurement/measurement.py b/src/akkudoktoreos/measurement/measurement.py index 3ad2442..e696e95 100644 --- a/src/akkudoktoreos/measurement/measurement.py +++ b/src/akkudoktoreos/measurement/measurement.py @@ -176,7 +176,7 @@ class Measurement(SingletonMixin, DataImportMixin, DataSequence): logger.debug(debug_msg) return energy_array - def load_total( + def load_total_kwh( self, start_datetime: Optional[DateTime] = None, end_datetime: Optional[DateTime] = None, @@ -207,7 +207,7 @@ class Measurement(SingletonMixin, DataImportMixin, DataSequence): if end_datetime is None: end_datetime = self[-1].date_time size = self._interval_count(start_datetime, end_datetime, interval) - load_total_array = np.zeros(size) + load_total_kwh_array = np.zeros(size) # Loop through all loads if isinstance(self.config.measurement.load_emr_keys, list): for key in self.config.measurement.load_emr_keys: @@ -219,11 +219,11 @@ class Measurement(SingletonMixin, DataImportMixin, DataSequence): interval=interval, ) # Add calculated load to total load - load_total_array += load_array - debug_msg = f"Total load '{key}' calculation: {load_total_array}" + load_total_kwh_array += load_array + debug_msg = f"Total load '{key}' calculation: {load_total_kwh_array}" logger.debug(debug_msg) - return load_total_array + return load_total_kwh_array def get_measurement() -> Measurement: diff --git a/src/akkudoktoreos/prediction/loadakkudoktor.py b/src/akkudoktoreos/prediction/loadakkudoktor.py index b8aa11e..26ebbe9 100644 --- a/src/akkudoktoreos/prediction/loadakkudoktor.py +++ b/src/akkudoktoreos/prediction/loadakkudoktor.py @@ -124,23 +124,23 @@ class LoadAkkudoktorAdjusted(LoadAkkudoktor): compare_end = self.measurement.max_datetime compare_interval = to_duration("1 hour") - load_total_array = self.measurement.load_total( + load_total_kwh_array = self.measurement.load_total_kwh( start_datetime=compare_start, end_datetime=compare_end, interval=compare_interval, ) compare_dt = compare_start - for i in range(len(load_total_array)): - load_total = load_total_array[i] + for i in range(len(load_total_kwh_array)): + load_total_wh = load_total_kwh_array[i] * 1000 # Extract mean (index 0) and standard deviation (index 1) for the given day and hour # Day indexing starts at 0, -1 because of that hourly_stats = data_year_energy[compare_dt.day_of_year - 1, :, compare_dt.hour] weight = 1 / ((compare_end - compare_dt).days + 1) if compare_dt.day_of_week < 5: - weekday_adjust[compare_dt.hour] += (load_total - hourly_stats[0]) * weight + weekday_adjust[compare_dt.hour] += (load_total_wh - hourly_stats[0]) * weight weekday_adjust_weight[compare_dt.hour] += weight else: - weekend_adjust[compare_dt.hour] += (load_total - hourly_stats[0]) * weight + weekend_adjust[compare_dt.hour] += (load_total_wh - hourly_stats[0]) * weight weekend_adjust_weight[compare_dt.hour] += weight compare_dt += compare_interval # Calculate mean diff --git a/tests/test_loadakkudoktor.py b/tests/test_loadakkudoktor.py index 6d61a95..eb42831 100644 --- a/tests/test_loadakkudoktor.py +++ b/tests/test_loadakkudoktor.py @@ -56,9 +56,10 @@ def loadakkudoktoradjusted(config_eos): @pytest.fixture def measurement_eos(): """Fixture to initialise the Measurement instance.""" + # Load meter readings are in kWh measurement = get_measurement() - load0_mr = 500 - load1_mr = 500 + load0_mr = 500.0 + load1_mr = 500.0 dt = to_datetime("2024-01-01T00:00:00") interval = to_duration("1 hour") for i in range(25): @@ -70,8 +71,9 @@ def measurement_eos(): ) ) dt += interval - load0_mr += 50 - load1_mr += 50 + # 0.05 kWh = 50 Wh + load0_mr += 0.05 + load1_mr += 0.05 assert compare_datetimes(measurement.min_datetime, to_datetime("2024-01-01T00:00:00")).equal assert compare_datetimes(measurement.max_datetime, to_datetime("2024-01-02T00:00:00")).equal return measurement @@ -187,7 +189,7 @@ def test_calculate_adjustment(loadakkudoktoradjusted, measurement_eos): 100.0, ] ) - np.testing.assert_array_equal(weekday_adjust, expected) + np.testing.assert_allclose(weekday_adjust, expected) assert weekend_adjust.shape == (24,) expected = np.array( diff --git a/tests/test_measurement.py b/tests/test_measurement.py index ef8148c..efba602 100644 --- a/tests/test_measurement.py +++ b/tests/test_measurement.py @@ -217,6 +217,7 @@ class TestMeasurement: @pytest.fixture def measurement_eos(self, config_eos): """Fixture to create a Measurement instance.""" + # Load meter readings are in kWh config_eos.measurement.load_emr_keys = ["load0_mr", "load1_mr", "load2_mr", "load3_mr"] measurement = get_measurement() record0 = MeasurementDataRecord( @@ -365,35 +366,35 @@ class TestMeasurement: with pytest.raises(ValueError, match="interval must be positive"): measurement_eos._energy_from_meter_readings(key, start_datetime, end_datetime, interval) - def test_load_total(self, measurement_eos): + def test_load_total_kwh(self, measurement_eos): """Test total load calculation.""" start = datetime(2023, 1, 1, 0) end = datetime(2023, 1, 1, 2) interval = duration(hours=1) - result = measurement_eos.load_total(start_datetime=start, end_datetime=end, interval=interval) + result = measurement_eos.load_total_kwh(start_datetime=start, end_datetime=end, interval=interval) # Expected total load per interval expected = np.array([100, 100]) # Differences between consecutive meter readings np.testing.assert_array_equal(result, expected) - def test_load_total_no_data(self, measurement_eos): + def test_load_total_kwh_no_data(self, measurement_eos): """Test total load calculation with no data.""" measurement_eos.records = [] start = datetime(2023, 1, 1, 0) end = datetime(2023, 1, 1, 3) interval = duration(hours=1) - result = measurement_eos.load_total(start_datetime=start, end_datetime=end, interval=interval) + result = measurement_eos.load_total_kwh(start_datetime=start, end_datetime=end, interval=interval) expected = np.zeros(3) # No data, so all intervals are zero np.testing.assert_array_equal(result, expected) - def test_load_total_partial_intervals(self, measurement_eos): + def test_load_total_kwh_partial_intervals(self, measurement_eos): """Test total load calculation with partial intervals.""" start = datetime(2023, 1, 1, 0, 30) # Start in the middle of an interval end = datetime(2023, 1, 1, 1, 30) # End in the middle of another interval interval = duration(hours=1) - result = measurement_eos.load_total(start_datetime=start, end_datetime=end, interval=interval) + result = measurement_eos.load_total_kwh(start_datetime=start, end_datetime=end, interval=interval) expected = np.array([100]) # Only one complete interval covered np.testing.assert_array_equal(result, expected)