openenergyid 0.1.13__py2.py3-none-any.whl → 0.1.15__py2.py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of openenergyid might be problematic. Click here for more details.

openenergyid/__init__.py CHANGED
@@ -1,6 +1,6 @@
1
1
  """Open Energy ID Python SDK."""
2
2
 
3
- __version__ = "0.1.13"
3
+ __version__ = "0.1.15"
4
4
 
5
5
  from .enums import Granularity
6
6
  from .models import TimeDataFrame, TimeSeries
@@ -0,0 +1,34 @@
1
+ import datetime
2
+
3
+ from openenergyid.capacity.models import CapacityInput
4
+
5
+
6
+ class PowerPeakAnalysis:
7
+ """analysis
8
+ This class is used to analyze the power peaks of a given time series.
9
+ The analysis is based on the following parameters:
10
+ - min_peak_value: The minimum value of a peak to be considered a peak.
11
+ - num_peaks: The number of peaks to be returned.
12
+ - from_date: The start date of the analysis.
13
+ - to_date: The end date of the analysis.
14
+ - x_padding: The number of days to be added to the start and end date to
15
+ ensure that the peaks are not cut off.
16
+ - capacity_input: The input data for the analysis.
17
+ """
18
+
19
+ def __init__(
20
+ self,
21
+ min_peak_value: float,
22
+ num_peaks: int,
23
+ from_date: datetime,
24
+ to_date: datetime,
25
+ x_padding: int = 2,
26
+ capacity_input=CapacityInput,
27
+ ):
28
+ self.data = input.get_series()
29
+ self.timezone = capacity_input.timezone
30
+ self.min_peak_value = min_peak_value
31
+ self.num_peaks = num_peaks
32
+ self.from_date = from_date
33
+ self.to_date = to_date
34
+ self.x_padding = x_padding
@@ -0,0 +1,6 @@
1
+ """Power Offtake peak analysis module."""
2
+
3
+ from .models import CapacityInput, CapacityOutput, PeakDetail
4
+ from .main import CapacityAnalysis
5
+
6
+ __all__ = ["CapacityInput", "CapacityAnalysis", "CapacityOutput", "PeakDetail"]
@@ -0,0 +1,90 @@
1
+ """Main module for capacity analysis."""
2
+
3
+ import datetime as dt
4
+ import pandas as pd
5
+
6
+
7
+ class CapacityAnalysis:
8
+ """
9
+ A class for performing capacity analysis on a given dataset.
10
+
11
+ Attributes:
12
+ data (CapacityInput): The input data for capacity analysis.
13
+ threshold (float): The value above which a peak is considered significant.
14
+ window (str): The window size for grouping data before finding peaks. Defaults to "MS" (month start).
15
+ x_padding (int): The padding to apply on the x-axis for visualization purposes.
16
+
17
+ Methods:
18
+ find_peaks(): Identifies peaks in the data based on the specified threshold and window.
19
+ find_peaks_with_surroundings(num_peaks=10): Finds peaks along with their surrounding data points.
20
+ """
21
+
22
+ def __init__(
23
+ self,
24
+ data: pd.Series,
25
+ threshold: float = 2.5,
26
+ window: str = "MS", # Default to month start
27
+ x_padding: int = 4,
28
+ ):
29
+ """
30
+ Constructs all the necessary attributes for the CapacityAnalysis object.
31
+
32
+ Parameters:
33
+ data (CapacityInput): Localized Pandas Series containing power measurements.
34
+ threshold (float): The value above which a peak is considered significant. Defaults to 2.5.
35
+ window (str): The window size for grouping data before finding peaks. Defaults to "MS" (month start).
36
+ x_padding (int): The padding to apply on the x-axis for visualization purposes. Defaults to 4.
37
+ """
38
+
39
+ self.data = data
40
+ self.threshold = threshold
41
+ self.window = window
42
+ self.x_padding = x_padding
43
+
44
+ def find_peaks(self) -> pd.Series:
45
+ """
46
+ Identifies peaks in the data based on the specified threshold and window.
47
+
48
+ Returns:
49
+ pd.Series: A Pandas Series containing the peaks
50
+ """
51
+ # Group by the specified window (default is month start)
52
+ grouped = self.data.groupby(pd.Grouper(freq=self.window))
53
+ # Find the index (timestamp) of the maximum value in each group
54
+ peak_indices = grouped.idxmax()
55
+ # Get the corresponding peak values
56
+ peaks = self.data.loc[peak_indices][self.data > self.threshold]
57
+
58
+ return peaks
59
+
60
+ def find_peaks_with_surroundings(
61
+ self, num_peaks: int = 10
62
+ ) -> list[tuple[dt.datetime, float, pd.Series]]:
63
+ """
64
+ Finds peaks along with their surrounding data points.
65
+
66
+ Parameters:
67
+ num_peaks (int): The number of peaks to find. Defaults to 10.
68
+
69
+ Returns:
70
+ List[tuple[dt.datetime,float,pd.Series]]: A list of tuples containing peak time, peak value, and surrounding data.
71
+ """
72
+ peaks = self.data.sort_values(ascending=False).head(num_peaks)
73
+ peaks = peaks[peaks > self.threshold]
74
+ if peaks.empty:
75
+ return []
76
+ result = []
77
+ for peak_time, peak_value in peaks.items():
78
+ start_time = peak_time - dt.timedelta(minutes=15 * self.x_padding)
79
+ end_time = peak_time + dt.timedelta(minutes=15 * (self.x_padding + 1))
80
+ surrounding_data = self.data[start_time:end_time]
81
+
82
+ result.append(
83
+ [
84
+ peak_time,
85
+ peak_value,
86
+ surrounding_data,
87
+ ]
88
+ )
89
+
90
+ return result
@@ -0,0 +1,29 @@
1
+ """Model for Capacity Analysis."""
2
+
3
+ import datetime as dt
4
+ from pydantic import BaseModel, ConfigDict, Field
5
+ from openenergyid.models import TimeSeries
6
+
7
+
8
+ class CapacityInput(BaseModel):
9
+ """Model for capacity input"""
10
+
11
+ timezone: str = Field(alias="timeZone")
12
+ series: TimeSeries
13
+
14
+
15
+ class PeakDetail(BaseModel):
16
+ """Model for peak detail"""
17
+
18
+ peak_time: dt.datetime = Field(alias="peakTime")
19
+ peak_value: float = Field(alias="peakValue")
20
+ surrounding_data: TimeSeries = Field(alias="surroundingData")
21
+ model_config = ConfigDict(populate_by_name=True)
22
+
23
+
24
+ class CapacityOutput(BaseModel):
25
+ """Model for capacity output"""
26
+
27
+ peaks: TimeSeries
28
+ peak_details: list[PeakDetail] = Field(alias="peakDetails")
29
+ model_config = ConfigDict(populate_by_name=True)
@@ -1,6 +1,5 @@
1
1
  """Main module of the DynTar package."""
2
2
 
3
- from typing import Optional
4
3
  import pandas as pd
5
4
 
6
5
  from openenergyid.const import (
@@ -40,7 +39,7 @@ def weigh_by_monthly_profile(series: pd.Series, profile: pd.Series) -> pd.Series
40
39
  return pd.concat(results)["weighted"]
41
40
 
42
41
 
43
- def extend_dataframe_with_smr2(df: pd.DataFrame, inplace: bool = False) -> Optional[pd.DataFrame]:
42
+ def extend_dataframe_with_smr2(df: pd.DataFrame, inplace: bool = False) -> pd.DataFrame | None:
44
43
  """Extend a DataFrame with the SMR2 columns."""
45
44
  if not inplace:
46
45
  result_df = df.copy()
@@ -67,7 +66,7 @@ def extend_dataframe_with_smr2(df: pd.DataFrame, inplace: bool = False) -> Optio
67
66
  return None
68
67
 
69
68
 
70
- def extend_dataframe_with_costs(df: pd.DataFrame, inplace: bool = False) -> Optional[pd.DataFrame]:
69
+ def extend_dataframe_with_costs(df: pd.DataFrame, inplace: bool = False) -> pd.DataFrame | None:
71
70
  """Extend a DataFrame with the cost columns."""
72
71
  if not inplace:
73
72
  result_df = df.copy()
@@ -95,7 +94,7 @@ def extend_dataframe_with_costs(df: pd.DataFrame, inplace: bool = False) -> Opti
95
94
 
96
95
  def extend_dataframe_with_weighted_prices(
97
96
  df: pd.DataFrame, inplace: bool = False
98
- ) -> Optional[pd.DataFrame]:
97
+ ) -> pd.DataFrame | None:
99
98
  """Extend a DataFrame with the weighted price columns."""
100
99
  if not inplace:
101
100
  df = df.copy()
@@ -118,9 +117,7 @@ def extend_dataframe_with_weighted_prices(
118
117
  return None
119
118
 
120
119
 
121
- def extend_dataframe_with_heatmap(
122
- df: pd.DataFrame, inplace: bool = False
123
- ) -> Optional[pd.DataFrame]:
120
+ def extend_dataframe_with_heatmap(df: pd.DataFrame, inplace: bool = False) -> pd.DataFrame | None:
124
121
  """Extend a DataFrame with the heatmap columns."""
125
122
  if not inplace:
126
123
  df = df.copy()
@@ -154,7 +151,7 @@ def extend_dataframe_with_heatmap(
154
151
  return None
155
152
 
156
153
 
157
- def calculate_dyntar_columns(df: pd.DataFrame, inplace: bool = False) -> Optional[pd.DataFrame]:
154
+ def calculate_dyntar_columns(df: pd.DataFrame, inplace: bool = False) -> pd.DataFrame | None:
158
155
  """Calculate all columns required for the dynamic tariff analysis."""
159
156
  if not inplace:
160
157
  df = df.copy()
@@ -41,7 +41,6 @@ def create_multi_index_output_frame(
41
41
 
42
42
  df = pd.concat([net_injection, net_offtake, shared_energy], axis=1)
43
43
 
44
- df = df.round(2)
45
44
  return df
46
45
 
47
46
 
@@ -16,23 +16,24 @@ def _calculate(df: pd.DataFrame, method: CalculationMethod) -> pd.DataFrame:
16
16
  injections_to_share = []
17
17
  rest = {}
18
18
 
19
- for participant in df.columns.levels[1]:
19
+ for participant in df[GROSS_INJECTION].columns:
20
20
  injection_to_share = df[GROSS_INJECTION][participant].copy()
21
21
 
22
+ key = df[KEY].copy()
22
23
  if method == CalculationMethod.RELATIVE or method == CalculationMethod.OPTIMAL:
23
24
  # Set the key of the current participant to 0
24
25
  # Re-normalize the keys for the other participants
25
- key = df[KEY].copy()
26
- key.loc[:, participant] = 0
27
- key = key.div(key.sum(axis=1), axis=0)
28
- elif method == CalculationMethod.FIXED:
29
- key = df[KEY].copy()
26
+ if participant in df[KEY].columns:
27
+ key.loc[:, participant] = 0
28
+ key = key.div(key.sum(axis=1), axis=0)
30
29
 
31
30
  # Multiply injection_to_share with the key of each participant
32
31
  shared_by_participant = (injection_to_share * key.T).T
33
32
  shared_by_participant.fillna(0, inplace=True)
33
+
34
34
  # Set the value for the current participant to 0
35
- shared_by_participant.loc[:, participant] = 0
35
+ if participant in shared_by_participant.columns:
36
+ shared_by_participant.loc[:, participant] = 0
36
37
 
37
38
  # Put the not shared injection in the rest
38
39
  rest[participant] = injection_to_share - shared_by_participant.sum(axis=1)
@@ -51,7 +52,7 @@ def _calculate(df: pd.DataFrame, method: CalculationMethod) -> pd.DataFrame:
51
52
  net_offtake = df[GROSS_OFFTAKE] - max_allocated_injection
52
53
 
53
54
  # Sum all negative values into a column "Not Shared"
54
- not_shared_after_assignment = net_offtake.clip(upper=0).sum(axis=1) * -1
55
+ not_shared_after_assignment = net_offtake.clip(upper=0).sum(axis=1).abs()
55
56
 
56
57
  # Clip the values to 0
57
58
  net_offtake = net_offtake.clip(lower=0)
@@ -34,7 +34,7 @@ class KeyInput(TimeDataFrame):
34
34
  def model_post_init(self, __context: Any) -> None:
35
35
  """Post-initialization validation."""
36
36
  for row in self.data:
37
- if round(sum(row), 6) != 1:
37
+ if round(sum(row), 3) != 1.0:
38
38
  raise ValueError("Each row must sum to 1.")
39
39
  return super().model_post_init(__context)
40
40
 
openenergyid/models.py CHANGED
@@ -1,15 +1,12 @@
1
1
  """Data models for the Open Energy ID."""
2
2
 
3
3
  import datetime as dt
4
- from typing import Optional, overload, Union
4
+ from typing import overload
5
5
 
6
- try:
7
- from typing import Self
8
- except ImportError:
9
- from typing_extensions import Self
6
+ from typing import Self
10
7
 
11
8
  import pandas as pd
12
- from pydantic import BaseModel
9
+ from pydantic import BaseModel, field_validator
13
10
 
14
11
 
15
12
  class TimeSeriesBase(BaseModel):
@@ -18,11 +15,11 @@ class TimeSeriesBase(BaseModel):
18
15
  index: list[dt.datetime]
19
16
 
20
17
  @classmethod
21
- def from_pandas(cls, data: Union[pd.Series, pd.DataFrame]) -> Self:
18
+ def from_pandas(cls, data: pd.Series | pd.DataFrame) -> Self:
22
19
  """Create from a Pandas Object."""
23
20
  raise NotImplementedError
24
21
 
25
- def to_pandas(self, timezone: str = "UTC") -> Union[pd.Series, pd.DataFrame]:
22
+ def to_pandas(self, timezone: str = "UTC") -> pd.Series | pd.DataFrame:
26
23
  """Convert to a Pandas Object."""
27
24
  raise NotImplementedError
28
25
 
@@ -34,7 +31,7 @@ class TimeSeriesBase(BaseModel):
34
31
  def to_json(self, path: str, **kwargs) -> None:
35
32
  """Dump to a JSON file."""
36
33
 
37
- def to_json(self, path: Optional[str] = None, **kwargs) -> Optional[str]:
34
+ def to_json(self, path: str | None = None, **kwargs) -> str | None:
38
35
  """Dump to a JSON string or file."""
39
36
  if path is None:
40
37
  return self.model_dump_json(**kwargs)
@@ -50,17 +47,17 @@ class TimeSeriesBase(BaseModel):
50
47
 
51
48
  @overload
52
49
  @classmethod
53
- def from_json(cls, path: str, **kwargs) -> Self:
50
+ def from_json(cls, *, path: str, **kwargs) -> Self:
54
51
  """Load from a JSON file."""
55
52
 
56
53
  @classmethod
57
- def from_json(cls, string: Optional[str] = None, path: Optional[str] = None, **kwargs) -> Self:
54
+ def from_json(cls, string: str | None = None, path: str | None = None, **kwargs) -> Self:
58
55
  """Load from a JSON file or string."""
59
56
  if string:
60
57
  return cls.model_validate_json(string, **kwargs)
61
58
  if path:
62
59
  encoding = kwargs.pop("encoding", "UTF-8")
63
- with open(path, "r", encoding=encoding) as file:
60
+ with open(path, encoding=encoding) as file:
64
61
  return cls.model_validate_json(file.read(), **kwargs)
65
62
  raise ValueError("Either string or path must be provided.")
66
63
 
@@ -68,13 +65,19 @@ class TimeSeriesBase(BaseModel):
68
65
  class TimeSeries(TimeSeriesBase):
69
66
  """Time series data with a single column."""
70
67
 
71
- name: Union[str, None] = None
72
- data: list[float]
68
+ name: str | None = None
69
+ data: list[float | None]
70
+
71
+ @field_validator("data")
72
+ @classmethod
73
+ def replace_nan_with_none(cls, data: list[float]) -> list[float | None]:
74
+ """Replace NaN values with None."""
75
+ return [None if pd.isna(value) else value for value in data]
73
76
 
74
77
  @classmethod
75
78
  def from_pandas(cls, data: pd.Series) -> Self:
76
79
  """Create from a Pandas Series."""
77
- return cls.model_construct(name=data.name, data=data.tolist(), index=data.index.tolist())
80
+ return cls(name=str(data.name), data=data.tolist(), index=data.index.tolist())
78
81
 
79
82
  def to_pandas(self, timezone: str = "UTC") -> pd.Series:
80
83
  """Convert to a Pandas Series."""
@@ -87,12 +90,18 @@ class TimeDataFrame(TimeSeriesBase):
87
90
  """Time series data with multiple columns."""
88
91
 
89
92
  columns: list[str]
90
- data: list[list[float]]
93
+ data: list[list[float | None]]
94
+
95
+ @field_validator("data")
96
+ @classmethod
97
+ def replace_nan_with_none(cls, data: list[list[float]]) -> list[list[float | None]]:
98
+ """Replace NaN values with None."""
99
+ return [[None if pd.isna(value) else value for value in row] for row in data]
91
100
 
92
101
  @classmethod
93
102
  def from_pandas(cls, data: pd.DataFrame) -> Self:
94
103
  """Create from a Pandas DataFrame."""
95
- return cls.model_construct(
104
+ return cls(
96
105
  columns=data.columns.tolist(), data=data.values.tolist(), index=data.index.tolist()
97
106
  )
98
107
 
@@ -1,5 +1,6 @@
1
1
  """Models for multivariable linear regression."""
2
- from typing import Any, List, Optional
2
+
3
+ from typing import Any
3
4
  import pandas as pd
4
5
 
5
6
  from pydantic import BaseModel, Field, ConfigDict
@@ -45,7 +46,7 @@ class IndependentVariableInput(BaseModel):
45
46
  "If the name is `temperatureEquivalent`, "
46
47
  "it will be unpacked into columns according to the variants."
47
48
  )
48
- variants: Optional[list[str]] = Field(
49
+ variants: list[str] | None = Field(
49
50
  default=None,
50
51
  description="Variants of the `temperatureEquivalent` independent variable. "
51
52
  "Eg. `HDD_16.5` will be Heating Degree Days with a base temperature of 16.5°C, "
@@ -62,7 +63,7 @@ class MultiVariableRegressionInput(BaseModel):
62
63
  """Multi-variable regression input."""
63
64
 
64
65
  timezone: str = Field(alias="timeZone")
65
- independent_variables: List[IndependentVariableInput] = Field(
66
+ independent_variables: list[IndependentVariableInput] = Field(
66
67
  alias="independentVariables", min_length=1
67
68
  )
68
69
  dependent_variable: str = Field(alias="dependentVariable")
@@ -72,7 +73,7 @@ class MultiVariableRegressionInput(BaseModel):
72
73
  validation_parameters: ValidationParameters = Field(
73
74
  alias="validationParameters", default=ValidationParameters()
74
75
  )
75
- single_use_exog_prefixes: Optional[List[str]] = Field(
76
+ single_use_exog_prefixes: list[str] | None = Field(
76
77
  # default=["HDD", "CDD", "FDD"],
77
78
  default=None,
78
79
  alias="singleUseExogPrefixes",
@@ -128,7 +129,7 @@ class MultiVariableRegressionInput(BaseModel):
128
129
 
129
130
  return frame
130
131
 
131
- def get_disallowed_negative_coefficients(self) -> List[str]:
132
+ def get_disallowed_negative_coefficients(self) -> list[str]:
132
133
  """Get independent variables that are not allowed to have a negative coefficient."""
133
134
  result = []
134
135
  for iv in self.independent_variables: # pylint: disable=not-an-iterable
@@ -158,12 +159,10 @@ class IndependentVariableResult(BaseModel):
158
159
 
159
160
  name: str
160
161
  coef: float
161
- t_stat: Optional[float] = Field(default=None, alias="tStat")
162
- p_value: Optional[float] = Field(ge=0, le=1, default=None, alias="pValue")
163
- std_err: Optional[float] = Field(default=None, alias="stdErr")
164
- confidence_interval: Optional[ConfidenceInterval] = Field(
165
- default=None, alias="confidenceInterval"
166
- )
162
+ t_stat: float | None = Field(default=None, alias="tStat")
163
+ p_value: float | None = Field(ge=0, le=1, default=None, alias="pValue")
164
+ std_err: float | None = Field(default=None, alias="stdErr")
165
+ confidence_interval: ConfidenceInterval | None = Field(default=None, alias="confidenceInterval")
167
166
 
168
167
  model_config = ConfigDict(populate_by_name=True)
169
168
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: openenergyid
3
- Version: 0.1.13
3
+ Version: 0.1.15
4
4
  Summary: Open Source Python library for energy analytics and simulations
5
5
  Project-URL: Homepage, https://energyid.eu
6
6
  Project-URL: Repository, https://github.com/EnergieID/OpenEnergyID
@@ -44,4 +44,7 @@ Classifier: Topic :: Software Development :: Libraries :: Python Modules
44
44
  Description-Content-Type: text/markdown
45
45
 
46
46
  # OpenEnergyID
47
+
47
48
  Open Source Python library for energy data analytics and simulations
49
+
50
+ [*more info for developers*](DEVELOPERS.md)
@@ -0,0 +1,26 @@
1
+ openenergyid/__init__.py,sha256=I9GYYWvktnGpJGRAg-NQAnKsFGnNytEgHJNBlaMO3bo,193
2
+ openenergyid/const.py,sha256=D-xUnUyVuLmphClkePgxpFP6z0RDhw_6m7rX0BHBgrw,823
3
+ openenergyid/enums.py,sha256=jdw4CB1gkisx0re_SesrTEyh_T-UxYp6uieE7iYlHdA,357
4
+ openenergyid/models.py,sha256=oAX5JI_aytpJTc63Pd7c1BbhhKoOC8T3zx9ChOOC_X4,4365
5
+ openenergyid/capacity/PowerAnalysis.py,sha256=V3-CupATVMQ95U-GWVumAbhj4IccHW-aAc4-Gsq7kWk,1136
6
+ openenergyid/capacity/__init__.py,sha256=1En96HlPV8kd1hOJO9RjRbXNInp5ZSkmjsjp0jfZlcQ,221
7
+ openenergyid/capacity/main.py,sha256=RLTPOopVW11vSAp-FxsalnzrinwQRnc2LzhJt1RpLMk,3335
8
+ openenergyid/capacity/models.py,sha256=rsxp3tP7_Vk9Qy3EypB9XeTKPpeXk2xRU1GuoT1vUwQ,784
9
+ openenergyid/dyntar/__init__.py,sha256=iQXQXrEQOiVNeeF6LRmUf3oOhKlGjMNF7o4T04IWTGA,371
10
+ openenergyid/dyntar/const.py,sha256=K7X6nHIl9DNyC6hU8jLtvOy3-IBGuYC449evOpImuJE,773
11
+ openenergyid/dyntar/main.py,sha256=cFfRZuwTVwHhXzR1pjKgQ4uhx4mMTAhjgFHJRMggKF8,5267
12
+ openenergyid/dyntar/models.py,sha256=BbGdHj7eUOMepblWJNsNd21xULluv6m7TtdhSggvVbY,1873
13
+ openenergyid/energysharing/__init__.py,sha256=A4JfrUYf-hBCzhUm0qL1GGlNMvpO8OwXJo80dJxFIvw,274
14
+ openenergyid/energysharing/const.py,sha256=X2zEPtTlsmZ66w6RmLS_h8NmdzObAEi5N6-0yrLN5V4,219
15
+ openenergyid/energysharing/data_formatting.py,sha256=Kwuhyn6ao_8Brdm9frlA6VzYOqimNYZsRbYwNXnE7yc,2583
16
+ openenergyid/energysharing/main.py,sha256=QKrtDyAlmKj0qtlqlUMjTJujQeKBK9U1_W80-RZWt-U,4449
17
+ openenergyid/energysharing/models.py,sha256=-FedTqWqoi7AYrbI4S_pX0bMScrbZxncQ21CXFz2cXM,2526
18
+ openenergyid/mvlr/__init__.py,sha256=Glrc218oqa8tq_Y2G9LXaSoN4Yba-vsjXUi9r9iPzaY,471
19
+ openenergyid/mvlr/helpers.py,sha256=Uzbfrj3IpH26wA206KOl0hNucKE-n9guJNC_EROBVKA,983
20
+ openenergyid/mvlr/main.py,sha256=cn7jZ98cHn2eh-0zG9q8Pad0Ft_FuI-u3a-eeHeF8jA,1304
21
+ openenergyid/mvlr/models.py,sha256=XvkViOLlYqi0ffgF3AD4Jvk3yL05gsoKdKgBAsGJ7L4,8581
22
+ openenergyid/mvlr/mvlr.py,sha256=F7WvWnZQtqUmK1vsguemsn9n8pDDk3tQ1weOlv-bo0c,18626
23
+ openenergyid-0.1.15.dist-info/METADATA,sha256=-ks_6DkMBz6YlvlF4_iZywL5Cc3b73gH9xjP7xXxy5I,2477
24
+ openenergyid-0.1.15.dist-info/WHEEL,sha256=fl6v0VwpzfGBVsGtkAkhILUlJxROXbA3HvRL6Fe3140,105
25
+ openenergyid-0.1.15.dist-info/licenses/LICENSE,sha256=NgRdcNHwyXVCXZ8sJwoTp0DCowThJ9LWWl4xhbV1IUY,1074
26
+ openenergyid-0.1.15.dist-info/RECORD,,
@@ -1,22 +0,0 @@
1
- openenergyid/__init__.py,sha256=rv5QjTRqWXVl6rEiphVaBPrzKnc-Hu1vlVS17R-v0GU,193
2
- openenergyid/const.py,sha256=D-xUnUyVuLmphClkePgxpFP6z0RDhw_6m7rX0BHBgrw,823
3
- openenergyid/enums.py,sha256=jdw4CB1gkisx0re_SesrTEyh_T-UxYp6uieE7iYlHdA,357
4
- openenergyid/models.py,sha256=ANdbdtr6JccSz6zEZj0TQOXISGPdtJPQy4t17uub97E,3975
5
- openenergyid/dyntar/__init__.py,sha256=iQXQXrEQOiVNeeF6LRmUf3oOhKlGjMNF7o4T04IWTGA,371
6
- openenergyid/dyntar/const.py,sha256=K7X6nHIl9DNyC6hU8jLtvOy3-IBGuYC449evOpImuJE,773
7
- openenergyid/dyntar/main.py,sha256=sn2zN5ep8XBgSGR_UDBU6mdp1WKNLzxROwp8HWCDgCM,5316
8
- openenergyid/dyntar/models.py,sha256=BbGdHj7eUOMepblWJNsNd21xULluv6m7TtdhSggvVbY,1873
9
- openenergyid/energysharing/__init__.py,sha256=A4JfrUYf-hBCzhUm0qL1GGlNMvpO8OwXJo80dJxFIvw,274
10
- openenergyid/energysharing/const.py,sha256=X2zEPtTlsmZ66w6RmLS_h8NmdzObAEi5N6-0yrLN5V4,219
11
- openenergyid/energysharing/data_formatting.py,sha256=RjP6NOyCXS9gI3x2NfQwHTJh9IbZJEExhXMZ4Zc0ImI,2604
12
- openenergyid/energysharing/main.py,sha256=2AWaTysNVLZEFVs8yRmFWx1_qG-NPeAazWXlFLHfLRM,4409
13
- openenergyid/energysharing/models.py,sha256=GQs7dsKxiShVKKIjNjvSgn6bafwFNuGZ8q6QnmslCjM,2524
14
- openenergyid/mvlr/__init__.py,sha256=Glrc218oqa8tq_Y2G9LXaSoN4Yba-vsjXUi9r9iPzaY,471
15
- openenergyid/mvlr/helpers.py,sha256=Uzbfrj3IpH26wA206KOl0hNucKE-n9guJNC_EROBVKA,983
16
- openenergyid/mvlr/main.py,sha256=cn7jZ98cHn2eh-0zG9q8Pad0Ft_FuI-u3a-eeHeF8jA,1304
17
- openenergyid/mvlr/models.py,sha256=qi5NWeQC1KeWEAO8KglgVM1xbHM5QoeK25ugn0W_X6c,8628
18
- openenergyid/mvlr/mvlr.py,sha256=F7WvWnZQtqUmK1vsguemsn9n8pDDk3tQ1weOlv-bo0c,18626
19
- openenergyid-0.1.13.dist-info/METADATA,sha256=9r6beVSt2i5VHjwsyEUnnHMR-lopo-S6-29yIq1s05E,2432
20
- openenergyid-0.1.13.dist-info/WHEEL,sha256=fl6v0VwpzfGBVsGtkAkhILUlJxROXbA3HvRL6Fe3140,105
21
- openenergyid-0.1.13.dist-info/licenses/LICENSE,sha256=NgRdcNHwyXVCXZ8sJwoTp0DCowThJ9LWWl4xhbV1IUY,1074
22
- openenergyid-0.1.13.dist-info/RECORD,,