gazpar2haws 0.3.0b19__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 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) -> np.ndarray: ...
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 + 1
74
- return self.array[start_index:end_index]
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
- def __setitem__(self, key, value: float):
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 + 1
99
- self.array[start_index:end_index] = value
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,17 +104,32 @@ 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
 
110
120
  # The end date is the last date of the daily history
111
- end_date = datetime.strptime(daily_history[-1][pygazpar.PropertyName.TIME_PERIOD.value], "%d/%m/%Y").date()
121
+ if daily_history is None or len(daily_history) == 0:
122
+ end_date = start_date
123
+ else:
124
+ end_date = datetime.strptime(daily_history[-1][pygazpar.PropertyName.TIME_PERIOD.value], "%d/%m/%Y").date()
125
+
126
+ Logger.debug(f"End date: {end_date}")
112
127
 
113
128
  # Extract the volume from the daily history
114
129
  volume_array = self.extract_property_from_daily_gazpar_history(
115
130
  daily_history,
116
131
  pygazpar.PropertyName.VOLUME.value,
117
- last_date_and_value_by_sensor[volume_sensor_name][0],
132
+ volume_start_date,
118
133
  end_date,
119
134
  )
120
135
 
@@ -122,7 +137,7 @@ class Gazpar:
122
137
  energy_array = self.extract_property_from_daily_gazpar_history(
123
138
  daily_history,
124
139
  pygazpar.PropertyName.ENERGY.value,
125
- last_date_and_value_by_sensor[energy_sensor_name][0],
140
+ min(energy_start_date, cost_start_date),
126
141
  end_date,
127
142
  )
128
143
 
@@ -137,11 +152,11 @@ class Gazpar:
137
152
  else:
138
153
  Logger.info("No volume data to publish")
139
154
 
140
- if energy_array is not None:
155
+ if energy_array is not None and energy_start_date <= end_date:
141
156
  await self.publish_date_array(
142
157
  energy_sensor_name,
143
158
  "kWh",
144
- energy_array,
159
+ energy_array[energy_start_date : end_date + timedelta(days=1)],
145
160
  last_date_and_value_by_sensor[energy_sensor_name][1],
146
161
  )
147
162
  else:
@@ -156,11 +171,11 @@ class Gazpar:
156
171
  pricer = Pricer(self._pricing_config)
157
172
 
158
173
  quantities = ConsumptionQuantityArray(
159
- start_date=last_date_and_value_by_sensor[energy_sensor_name][0],
174
+ start_date=cost_start_date,
160
175
  end_date=end_date,
161
176
  value_unit=QuantityUnit.KWH,
162
177
  base_unit=TimeUnit.DAY,
163
- value_array=energy_array,
178
+ value_array=energy_array[cost_start_date : end_date + timedelta(days=1)],
164
179
  )
165
180
 
166
181
  cost_array = pricer.compute(quantities, PriceUnit.EURO)
@@ -169,11 +184,12 @@ class Gazpar:
169
184
 
170
185
  # Publish the cost to Home Assistant
171
186
  if cost_array is not None:
187
+ cost_initial_value = last_date_and_value_by_sensor[cost_sensor_name][1]
172
188
  await self.publish_date_array(
173
189
  cost_sensor_name,
174
190
  cost_array.value_unit,
175
191
  cost_array.value_array,
176
- last_date_and_value_by_sensor[cost_sensor_name][1],
192
+ cost_initial_value,
177
193
  )
178
194
  else:
179
195
  Logger.info("No cost data to publish")
@@ -199,7 +215,15 @@ class Gazpar:
199
215
  endDate=end_date,
200
216
  frequencies=[pygazpar.Frequency.DAILY],
201
217
  )
202
- res = history[pygazpar.Frequency.DAILY.value]
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}")
203
227
  except Exception: # pylint: disable=broad-except
204
228
  Logger.warning(f"Error while fetching data from GrDF: {traceback.format_exc()}")
205
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] = first_value.value * (1 + vat_value) # type: ignore
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] = last_value.value * (1 + vat_value) # type: ignore
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] = first_value.value * (1 + vat_value) # type: ignore
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] = last_value.value * (1 + vat_value) # type: ignore
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] = value.value * (1 + vat_value) # type: ignore
410
+ value_array[current_date] = (vat_value + 1) * value.value # type: ignore
411
411
  current_date += timedelta(days=1)
412
412
 
413
413
  # ----------------------------------
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: gazpar2haws
3
- Version: 0.3.0b19
3
+ Version: 0.3.0b21
4
4
  Summary: Gazpar2HAWS is a gateway that reads data history from the GrDF (French gas provider) meter and send it to Home Assistant using WebSocket interface
5
5
  License: MIT License
6
6
 
@@ -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=XQ8gwTl0w97ADjs6igdMZLxtPPrDWTLQzhhzTDVjC4M,8761
7
- gazpar2haws/gazpar.py,sha256=kez6YDs-xVTc7eWaIr_LSsbl_g636eheb6ldHHz5TbY,12835
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=YhMfvAKSxQhE2JGgrkNOpqQZdTWjGZ_bUtNsYA0u2fs,21932
10
+ gazpar2haws/pricer.py,sha256=PcjRTBhOECzJCJ0mrIgS5agGf8N3O2u0mLVky-cbvhk,22124
11
11
  gazpar2haws/version.py,sha256=9Iq5Jm63Ev7QquCjhDqa9_KAgHdKl9FJHynq8M6JNrY,83
12
- gazpar2haws-0.3.0b19.dist-info/LICENSE,sha256=ajApZPyhVx8AU9wN7DXeRGhoWFqY2ylBZUa5GRhTmok,1073
13
- gazpar2haws-0.3.0b19.dist-info/METADATA,sha256=z45zOuNg614Z1dTOuQhXJkNV8lYnNVOc2wzP3v0j2wU,17406
14
- gazpar2haws-0.3.0b19.dist-info/WHEEL,sha256=RaoafKOydTQ7I_I3JTrPCg6kUmTgtm4BornzOqyEfJ8,88
15
- gazpar2haws-0.3.0b19.dist-info/RECORD,,
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,,