gazpar2haws 0.3.0b20__py3-none-any.whl → 0.3.0b21__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.
- gazpar2haws/date_array.py +27 -6
- gazpar2haws/gazpar.py +30 -9
- gazpar2haws/pricer.py +13 -13
- {gazpar2haws-0.3.0b20.dist-info → gazpar2haws-0.3.0b21.dist-info}/METADATA +1 -1
- {gazpar2haws-0.3.0b20.dist-info → gazpar2haws-0.3.0b21.dist-info}/RECORD +7 -7
- {gazpar2haws-0.3.0b20.dist-info → gazpar2haws-0.3.0b21.dist-info}/LICENSE +0 -0
- {gazpar2haws-0.3.0b20.dist-info → gazpar2haws-0.3.0b21.dist-info}/WHEEL +0 -0
gazpar2haws/date_array.py
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
from __future__ import annotations
|
2
2
|
|
3
3
|
import datetime as dt
|
4
|
+
from datetime import timedelta
|
4
5
|
from typing import Optional, overload
|
5
6
|
|
6
7
|
import numpy as np
|
@@ -57,7 +58,7 @@ class DateArray(BaseModel): # pylint: disable=too-few-public-methods
|
|
57
58
|
def __getitem__(self, date: dt.date) -> float: ...
|
58
59
|
|
59
60
|
@overload
|
60
|
-
def __getitem__(self, date_slice: slice) ->
|
61
|
+
def __getitem__(self, date_slice: slice) -> DateArray: ...
|
61
62
|
|
62
63
|
def __getitem__(self, key):
|
63
64
|
if self.array is None:
|
@@ -70,8 +71,14 @@ class DateArray(BaseModel): # pylint: disable=too-few-public-methods
|
|
70
71
|
start_date: dt.date = key.start # type: ignore
|
71
72
|
end_date: dt.date = key.stop # type: ignore
|
72
73
|
start_index: int = (start_date - self.start_date).days
|
73
|
-
end_index: int = (end_date - self.start_date).days
|
74
|
-
|
74
|
+
end_index: int = (end_date - self.start_date).days
|
75
|
+
if start_index < 0 or end_index > len(self.array):
|
76
|
+
raise ValueError(
|
77
|
+
f"Date slice [{start_date}:{end_date}] is out of range [{self.start_date}:{self.end_date}]"
|
78
|
+
)
|
79
|
+
return DateArray(
|
80
|
+
start_date=start_date, end_date=end_date + timedelta(-1), array=self.array[start_index:end_index]
|
81
|
+
)
|
75
82
|
raise TypeError("Key must be a date or a slice of dates")
|
76
83
|
|
77
84
|
# ----------------------------------
|
@@ -84,7 +91,10 @@ class DateArray(BaseModel): # pylint: disable=too-few-public-methods
|
|
84
91
|
@overload
|
85
92
|
def __setitem__(self, date_slice: slice, value: float): ...
|
86
93
|
|
87
|
-
|
94
|
+
@overload
|
95
|
+
def __setitem__(self, date_slice: slice, value: DateArray): ...
|
96
|
+
|
97
|
+
def __setitem__(self, key, value):
|
88
98
|
if self.array is None:
|
89
99
|
raise ValueError("Array is not initialized")
|
90
100
|
if isinstance(key, int):
|
@@ -95,8 +105,19 @@ class DateArray(BaseModel): # pylint: disable=too-few-public-methods
|
|
95
105
|
start_date: dt.date = key.start # type: ignore
|
96
106
|
end_date: dt.date = key.stop # type: ignore
|
97
107
|
start_index: int = (start_date - self.start_date).days
|
98
|
-
end_index: int = (end_date - self.start_date).days
|
99
|
-
self.array
|
108
|
+
end_index: int = (end_date - self.start_date).days
|
109
|
+
if start_index < 0 or end_index > len(self.array):
|
110
|
+
raise ValueError(
|
111
|
+
f"Date slice [{start_date}:{end_date}] is out of range [{self.start_date}:{self.end_date}]"
|
112
|
+
)
|
113
|
+
self.start_date = start_date
|
114
|
+
self.end_date = end_date + timedelta(-1)
|
115
|
+
if isinstance(value, float):
|
116
|
+
self.array[start_index:end_index] = value
|
117
|
+
elif isinstance(value, DateArray):
|
118
|
+
self.array[start_index:end_index] = value.array
|
119
|
+
else:
|
120
|
+
raise TypeError("Value must be a float or a DateArray")
|
100
121
|
else:
|
101
122
|
raise TypeError("Key must be a date or a slice of dates")
|
102
123
|
|
gazpar2haws/gazpar.py
CHANGED
@@ -78,7 +78,7 @@ class Gazpar:
|
|
78
78
|
|
79
79
|
# ----------------------------------
|
80
80
|
# Publish Gaspar data to Home Assistant WS
|
81
|
-
async def publish(self):
|
81
|
+
async def publish(self): # pylint: disable=too-many-branches, too-many-statements
|
82
82
|
|
83
83
|
# Volume, energy and cost sensor names.
|
84
84
|
volume_sensor_name = f"sensor.{self._name}_volume"
|
@@ -104,6 +104,16 @@ class Gazpar:
|
|
104
104
|
min(v[0] for v in last_date_and_value_by_sensor.values()) + timedelta(days=1), self._as_of_date
|
105
105
|
)
|
106
106
|
|
107
|
+
# Get all start dates
|
108
|
+
energy_start_date = last_date_and_value_by_sensor[energy_sensor_name][0] + timedelta(days=1)
|
109
|
+
volume_start_date = last_date_and_value_by_sensor[volume_sensor_name][0] + timedelta(days=1)
|
110
|
+
cost_start_date = last_date_and_value_by_sensor[cost_sensor_name][0] + timedelta(days=1)
|
111
|
+
|
112
|
+
Logger.debug(f"Min start date for all sensors: {start_date}")
|
113
|
+
Logger.debug(f"Energy start date: {energy_start_date}")
|
114
|
+
Logger.debug(f"Volume start date: {volume_start_date}")
|
115
|
+
Logger.debug(f"Cost start date: {cost_start_date}")
|
116
|
+
|
107
117
|
# Fetch the data from GrDF and publish it to Home Assistant
|
108
118
|
daily_history = self.fetch_daily_gazpar_history(start_date, self._as_of_date)
|
109
119
|
|
@@ -113,11 +123,13 @@ class Gazpar:
|
|
113
123
|
else:
|
114
124
|
end_date = datetime.strptime(daily_history[-1][pygazpar.PropertyName.TIME_PERIOD.value], "%d/%m/%Y").date()
|
115
125
|
|
126
|
+
Logger.debug(f"End date: {end_date}")
|
127
|
+
|
116
128
|
# Extract the volume from the daily history
|
117
129
|
volume_array = self.extract_property_from_daily_gazpar_history(
|
118
130
|
daily_history,
|
119
131
|
pygazpar.PropertyName.VOLUME.value,
|
120
|
-
|
132
|
+
volume_start_date,
|
121
133
|
end_date,
|
122
134
|
)
|
123
135
|
|
@@ -125,7 +137,7 @@ class Gazpar:
|
|
125
137
|
energy_array = self.extract_property_from_daily_gazpar_history(
|
126
138
|
daily_history,
|
127
139
|
pygazpar.PropertyName.ENERGY.value,
|
128
|
-
|
140
|
+
min(energy_start_date, cost_start_date),
|
129
141
|
end_date,
|
130
142
|
)
|
131
143
|
|
@@ -140,11 +152,11 @@ class Gazpar:
|
|
140
152
|
else:
|
141
153
|
Logger.info("No volume data to publish")
|
142
154
|
|
143
|
-
if energy_array is not None:
|
155
|
+
if energy_array is not None and energy_start_date <= end_date:
|
144
156
|
await self.publish_date_array(
|
145
157
|
energy_sensor_name,
|
146
158
|
"kWh",
|
147
|
-
energy_array,
|
159
|
+
energy_array[energy_start_date : end_date + timedelta(days=1)],
|
148
160
|
last_date_and_value_by_sensor[energy_sensor_name][1],
|
149
161
|
)
|
150
162
|
else:
|
@@ -159,11 +171,11 @@ class Gazpar:
|
|
159
171
|
pricer = Pricer(self._pricing_config)
|
160
172
|
|
161
173
|
quantities = ConsumptionQuantityArray(
|
162
|
-
start_date=
|
174
|
+
start_date=cost_start_date,
|
163
175
|
end_date=end_date,
|
164
176
|
value_unit=QuantityUnit.KWH,
|
165
177
|
base_unit=TimeUnit.DAY,
|
166
|
-
value_array=energy_array,
|
178
|
+
value_array=energy_array[cost_start_date : end_date + timedelta(days=1)],
|
167
179
|
)
|
168
180
|
|
169
181
|
cost_array = pricer.compute(quantities, PriceUnit.EURO)
|
@@ -172,11 +184,12 @@ class Gazpar:
|
|
172
184
|
|
173
185
|
# Publish the cost to Home Assistant
|
174
186
|
if cost_array is not None:
|
187
|
+
cost_initial_value = last_date_and_value_by_sensor[cost_sensor_name][1]
|
175
188
|
await self.publish_date_array(
|
176
189
|
cost_sensor_name,
|
177
190
|
cost_array.value_unit,
|
178
191
|
cost_array.value_array,
|
179
|
-
|
192
|
+
cost_initial_value,
|
180
193
|
)
|
181
194
|
else:
|
182
195
|
Logger.info("No cost data to publish")
|
@@ -202,7 +215,15 @@ class Gazpar:
|
|
202
215
|
endDate=end_date,
|
203
216
|
frequencies=[pygazpar.Frequency.DAILY],
|
204
217
|
)
|
205
|
-
|
218
|
+
|
219
|
+
# Filter the daily readings by keeping only dates between start_date and end_date
|
220
|
+
res = []
|
221
|
+
for reading in history[pygazpar.Frequency.DAILY.value]:
|
222
|
+
reading_date = datetime.strptime(reading[pygazpar.PropertyName.TIME_PERIOD.value], "%d/%m/%Y").date()
|
223
|
+
if start_date <= reading_date <= end_date:
|
224
|
+
res.append(reading)
|
225
|
+
|
226
|
+
Logger.debug(f"Fetched {len(res)} daily readings from start date {start_date} to end date {end_date}")
|
206
227
|
except Exception: # pylint: disable=broad-except
|
207
228
|
Logger.warning(f"Error while fetching data from GrDF: {traceback.format_exc()}")
|
208
229
|
res = MeterReadings()
|
gazpar2haws/pricer.py
CHANGED
@@ -315,17 +315,17 @@ class Pricer:
|
|
315
315
|
|
316
316
|
if first_value.start_date > end_date:
|
317
317
|
# Fully before first value period.
|
318
|
-
value_array[start_date:end_date] = first_value.value # type: ignore
|
318
|
+
value_array[start_date : end_date + timedelta(1)] = first_value.value # type: ignore
|
319
319
|
elif last_value.end_date is not None and last_value.end_date < start_date:
|
320
320
|
# Fully after last value period.
|
321
|
-
value_array[start_date:end_date] = last_value.value # type: ignore
|
321
|
+
value_array[start_date : end_date + timedelta(1)] = last_value.value # type: ignore
|
322
322
|
else:
|
323
323
|
if start_date < first_value.start_date:
|
324
324
|
# Partially before first value period.
|
325
|
-
value_array[start_date : first_value.start_date] = first_value.value # type: ignore
|
325
|
+
value_array[start_date : first_value.start_date + timedelta(1)] = first_value.value # type: ignore
|
326
326
|
if last_value.end_date is not None and end_date > last_value.end_date:
|
327
327
|
# Partially after last value period.
|
328
|
-
value_array[last_value.end_date : end_date] = last_value.value # type: ignore
|
328
|
+
value_array[last_value.end_date : end_date + timedelta(1)] = last_value.value # type: ignore
|
329
329
|
# Inside value periods.
|
330
330
|
for value in in_values:
|
331
331
|
latest_start = max(value.start_date, start_date)
|
@@ -371,32 +371,32 @@ class Pricer:
|
|
371
371
|
if first_value.start_date > end_date:
|
372
372
|
# Fully before first value period.
|
373
373
|
if vat_rate_array_by_id is not None and first_value.vat_id in vat_rate_array_by_id:
|
374
|
-
vat_value = vat_rate_array_by_id[first_value.vat_id].value_array[start_date:end_date] # type: ignore
|
374
|
+
vat_value = vat_rate_array_by_id[first_value.vat_id].value_array[start_date : end_date + timedelta(1)] # type: ignore
|
375
375
|
else:
|
376
376
|
vat_value = 0.0
|
377
|
-
value_array[start_date:end_date] =
|
377
|
+
value_array[start_date : end_date + timedelta(1)] = (vat_value + 1) * first_value.value # type: ignore
|
378
378
|
elif last_value.end_date is not None and last_value.end_date < start_date:
|
379
379
|
# Fully after last value period.
|
380
380
|
if vat_rate_array_by_id is not None and last_value.vat_id in vat_rate_array_by_id:
|
381
|
-
vat_value = vat_rate_array_by_id[last_value.vat_id].value_array[start_date:end_date] # type: ignore
|
381
|
+
vat_value = vat_rate_array_by_id[last_value.vat_id].value_array[start_date : end_date + timedelta(1)] # type: ignore
|
382
382
|
else:
|
383
383
|
vat_value = 0.0
|
384
|
-
value_array[start_date:end_date] =
|
384
|
+
value_array[start_date : end_date + timedelta(1)] = (vat_value + 1) * last_value.value # type: ignore
|
385
385
|
else:
|
386
386
|
if start_date < first_value.start_date:
|
387
387
|
# Partially before first value period.
|
388
388
|
if vat_rate_array_by_id is not None and first_value.vat_id in vat_rate_array_by_id:
|
389
|
-
vat_value = vat_rate_array_by_id[first_value.vat_id].value_array[start_date : first_value.start_date] # type: ignore
|
389
|
+
vat_value = vat_rate_array_by_id[first_value.vat_id].value_array[start_date : first_value.start_date + timedelta(1)] # type: ignore
|
390
390
|
else:
|
391
391
|
vat_value = 0.0
|
392
|
-
value_array[start_date : first_value.start_date] =
|
392
|
+
value_array[start_date : first_value.start_date + timedelta(1)] = (vat_value + 1) * first_value.value # type: ignore
|
393
393
|
if last_value.end_date is not None and end_date > last_value.end_date:
|
394
394
|
# Partially after last value period.
|
395
395
|
if vat_rate_array_by_id is not None and last_value.vat_id in vat_rate_array_by_id:
|
396
|
-
vat_value = vat_rate_array_by_id[last_value.vat_id].value_array[last_value.end_date : end_date] # type: ignore
|
396
|
+
vat_value = vat_rate_array_by_id[last_value.vat_id].value_array[last_value.end_date : end_date + timedelta(1)] # type: ignore
|
397
397
|
else:
|
398
398
|
vat_value = 0.0
|
399
|
-
value_array[last_value.end_date : end_date] =
|
399
|
+
value_array[last_value.end_date : end_date + timedelta(1)] = (vat_value + 1) * last_value.value # type: ignore
|
400
400
|
# Inside value periods.
|
401
401
|
for value in in_values:
|
402
402
|
latest_start = max(value.start_date, start_date)
|
@@ -407,7 +407,7 @@ class Pricer:
|
|
407
407
|
vat_value = vat_rate_array_by_id[value.vat_id].value_array[current_date] # type: ignore
|
408
408
|
else:
|
409
409
|
vat_value = 0.0
|
410
|
-
value_array[current_date] =
|
410
|
+
value_array[current_date] = (vat_value + 1) * value.value # type: ignore
|
411
411
|
current_date += timedelta(days=1)
|
412
412
|
|
413
413
|
# ----------------------------------
|
@@ -3,13 +3,13 @@ gazpar2haws/__main__.py,sha256=wD28dqa3weiz5cj9--hgLLN7FnW0eeA9ZmlIvriKXNk,3125
|
|
3
3
|
gazpar2haws/bridge.py,sha256=VEl22xt2Szgk_FVrxSvZNxp3T5Q2JXc9ulfrunHHkmo,3685
|
4
4
|
gazpar2haws/config_utils.py,sha256=yT2G-naMA2Vst6bQdm1bD2oVsPTU3Q_RuukCs-dZ6Ak,2280
|
5
5
|
gazpar2haws/configuration.py,sha256=24q8FUBMS1vpqU6RYAv5Au179HbiBk1CZIEMiBGuXq0,722
|
6
|
-
gazpar2haws/date_array.py,sha256=
|
7
|
-
gazpar2haws/gazpar.py,sha256=
|
6
|
+
gazpar2haws/date_array.py,sha256=RxvK_ZQxaeYCg4kg088_lMh5b1WDBa4wXPPqSIUDS2E,9779
|
7
|
+
gazpar2haws/gazpar.py,sha256=n3KugBo31_0nwql-QAiU9BHdDyIks139E3ENblgVNME,14224
|
8
8
|
gazpar2haws/haws.py,sha256=1ELdompdACNf5XkpjCN6Bdiw7stPfzar3x8OjoBmhxQ,7969
|
9
9
|
gazpar2haws/model.py,sha256=-1yhLNNcEvEtW67GMVLZ4lcXw6Lk75kWvrdjoVgjKCw,7055
|
10
|
-
gazpar2haws/pricer.py,sha256=
|
10
|
+
gazpar2haws/pricer.py,sha256=PcjRTBhOECzJCJ0mrIgS5agGf8N3O2u0mLVky-cbvhk,22124
|
11
11
|
gazpar2haws/version.py,sha256=9Iq5Jm63Ev7QquCjhDqa9_KAgHdKl9FJHynq8M6JNrY,83
|
12
|
-
gazpar2haws-0.3.
|
13
|
-
gazpar2haws-0.3.
|
14
|
-
gazpar2haws-0.3.
|
15
|
-
gazpar2haws-0.3.
|
12
|
+
gazpar2haws-0.3.0b21.dist-info/LICENSE,sha256=ajApZPyhVx8AU9wN7DXeRGhoWFqY2ylBZUa5GRhTmok,1073
|
13
|
+
gazpar2haws-0.3.0b21.dist-info/METADATA,sha256=sZuaDthuV50-HpNF4ghSIspSoRw80R9HnsikXbGjQNA,17406
|
14
|
+
gazpar2haws-0.3.0b21.dist-info/WHEEL,sha256=RaoafKOydTQ7I_I3JTrPCg6kUmTgtm4BornzOqyEfJ8,88
|
15
|
+
gazpar2haws-0.3.0b21.dist-info/RECORD,,
|
File without changes
|
File without changes
|