e-data 2.0.0.dev112__tar.gz → 2.0.0.dev121__tar.gz
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.
- {e_data-2.0.0.dev112/e_data.egg-info → e_data-2.0.0.dev121}/PKG-INFO +3 -3
- {e_data-2.0.0.dev112 → e_data-2.0.0.dev121}/README.md +2 -2
- {e_data-2.0.0.dev112 → e_data-2.0.0.dev121/e_data.egg-info}/PKG-INFO +3 -3
- {e_data-2.0.0.dev112 → e_data-2.0.0.dev121}/edata/cli.py +8 -8
- {e_data-2.0.0.dev112 → e_data-2.0.0.dev121}/edata/core/utils.py +1 -1
- {e_data-2.0.0.dev112 → e_data-2.0.0.dev121}/edata/database/controller.py +17 -15
- {e_data-2.0.0.dev112 → e_data-2.0.0.dev121}/edata/database/queries.py +3 -1
- {e_data-2.0.0.dev112 → e_data-2.0.0.dev121}/edata/database/utils.py +3 -4
- {e_data-2.0.0.dev112 → e_data-2.0.0.dev121}/edata/models/bill.py +5 -5
- e_data-2.0.0.dev121/edata/models/data.py +89 -0
- {e_data-2.0.0.dev112 → e_data-2.0.0.dev121}/edata/models/supply.py +14 -5
- {e_data-2.0.0.dev112 → e_data-2.0.0.dev121}/edata/providers/datadis.py +49 -51
- {e_data-2.0.0.dev112 → e_data-2.0.0.dev121}/edata/providers/redata.py +2 -2
- {e_data-2.0.0.dev112 → e_data-2.0.0.dev121}/edata/services/bill_service.py +15 -14
- {e_data-2.0.0.dev112 → e_data-2.0.0.dev121}/edata/services/data_service.py +35 -34
- {e_data-2.0.0.dev112 → e_data-2.0.0.dev121}/edata/tests/test_datadis_connector.py +85 -75
- {e_data-2.0.0.dev112 → e_data-2.0.0.dev121}/pyproject.toml +1 -1
- e_data-2.0.0.dev112/edata/models/data.py +0 -37
- {e_data-2.0.0.dev112 → e_data-2.0.0.dev121}/LICENSE +0 -0
- {e_data-2.0.0.dev112 → e_data-2.0.0.dev121}/MANIFEST.in +0 -0
- {e_data-2.0.0.dev112 → e_data-2.0.0.dev121}/e_data.egg-info/SOURCES.txt +0 -0
- {e_data-2.0.0.dev112 → e_data-2.0.0.dev121}/e_data.egg-info/dependency_links.txt +0 -0
- {e_data-2.0.0.dev112 → e_data-2.0.0.dev121}/e_data.egg-info/requires.txt +0 -0
- {e_data-2.0.0.dev112 → e_data-2.0.0.dev121}/e_data.egg-info/top_level.txt +0 -0
- {e_data-2.0.0.dev112 → e_data-2.0.0.dev121}/edata/__init__.py +0 -0
- {e_data-2.0.0.dev112 → e_data-2.0.0.dev121}/edata/core/__init__.py +0 -0
- {e_data-2.0.0.dev112 → e_data-2.0.0.dev121}/edata/core/const.py +0 -0
- {e_data-2.0.0.dev112 → e_data-2.0.0.dev121}/edata/database/__init__.py +0 -0
- {e_data-2.0.0.dev112 → e_data-2.0.0.dev121}/edata/database/models.py +0 -0
- {e_data-2.0.0.dev112 → e_data-2.0.0.dev121}/edata/models/__init__.py +0 -0
- {e_data-2.0.0.dev112 → e_data-2.0.0.dev121}/edata/providers/__init__.py +0 -0
- {e_data-2.0.0.dev112 → e_data-2.0.0.dev121}/edata/tests/__init__.py +0 -0
- {e_data-2.0.0.dev112 → e_data-2.0.0.dev121}/edata/tests/test_redata_connector.py +0 -0
- {e_data-2.0.0.dev112 → e_data-2.0.0.dev121}/edata/tests/test_services.py +0 -0
- {e_data-2.0.0.dev112 → e_data-2.0.0.dev121}/setup.cfg +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: e-data
|
|
3
|
-
Version: 2.0.0.
|
|
3
|
+
Version: 2.0.0.dev121
|
|
4
4
|
Summary: Python library for managing spanish energy data from various web providers
|
|
5
5
|
Author-email: VMG <vmayorg@outlook.es>
|
|
6
6
|
License: GNU GENERAL PUBLIC LICENSE
|
|
@@ -823,7 +823,7 @@ async def main():
|
|
|
823
823
|
# Mostrar resumen
|
|
824
824
|
total_cost = sum(b.value_eur for b in bills)
|
|
825
825
|
print(f"Coste total: {total_cost:.2f} €")
|
|
826
|
-
print(f"Consumo total: {sum(e.
|
|
826
|
+
print(f"Consumo total: {sum(e.value_kwh for e in energy):.2f} kWh")
|
|
827
827
|
|
|
828
828
|
# Ejecutar
|
|
829
829
|
asyncio.run(main())
|
|
@@ -841,7 +841,7 @@ python -m edata.cli show-supplies <username>
|
|
|
841
841
|
python -m edata.cli download-all --cups ES0000000000000000XX <username>
|
|
842
842
|
|
|
843
843
|
# Actualizar facturación con tarifa fija
|
|
844
|
-
python -m edata.cli update-bill \
|
|
844
|
+
python -m edata.cli update-custom-bill \
|
|
845
845
|
--cups ES0000000000000000XX \
|
|
846
846
|
--p1-kw-year-eur 30.67 \
|
|
847
847
|
--p2-kw-year-eur 1.42 \
|
|
@@ -119,7 +119,7 @@ async def main():
|
|
|
119
119
|
# Mostrar resumen
|
|
120
120
|
total_cost = sum(b.value_eur for b in bills)
|
|
121
121
|
print(f"Coste total: {total_cost:.2f} €")
|
|
122
|
-
print(f"Consumo total: {sum(e.
|
|
122
|
+
print(f"Consumo total: {sum(e.value_kwh for e in energy):.2f} kWh")
|
|
123
123
|
|
|
124
124
|
# Ejecutar
|
|
125
125
|
asyncio.run(main())
|
|
@@ -137,7 +137,7 @@ python -m edata.cli show-supplies <username>
|
|
|
137
137
|
python -m edata.cli download-all --cups ES0000000000000000XX <username>
|
|
138
138
|
|
|
139
139
|
# Actualizar facturación con tarifa fija
|
|
140
|
-
python -m edata.cli update-bill \
|
|
140
|
+
python -m edata.cli update-custom-bill \
|
|
141
141
|
--cups ES0000000000000000XX \
|
|
142
142
|
--p1-kw-year-eur 30.67 \
|
|
143
143
|
--p2-kw-year-eur 1.42 \
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: e-data
|
|
3
|
-
Version: 2.0.0.
|
|
3
|
+
Version: 2.0.0.dev121
|
|
4
4
|
Summary: Python library for managing spanish energy data from various web providers
|
|
5
5
|
Author-email: VMG <vmayorg@outlook.es>
|
|
6
6
|
License: GNU GENERAL PUBLIC LICENSE
|
|
@@ -823,7 +823,7 @@ async def main():
|
|
|
823
823
|
# Mostrar resumen
|
|
824
824
|
total_cost = sum(b.value_eur for b in bills)
|
|
825
825
|
print(f"Coste total: {total_cost:.2f} €")
|
|
826
|
-
print(f"Consumo total: {sum(e.
|
|
826
|
+
print(f"Consumo total: {sum(e.value_kwh for e in energy):.2f} kWh")
|
|
827
827
|
|
|
828
828
|
# Ejecutar
|
|
829
829
|
asyncio.run(main())
|
|
@@ -841,7 +841,7 @@ python -m edata.cli show-supplies <username>
|
|
|
841
841
|
python -m edata.cli download-all --cups ES0000000000000000XX <username>
|
|
842
842
|
|
|
843
843
|
# Actualizar facturación con tarifa fija
|
|
844
|
-
python -m edata.cli update-bill \
|
|
844
|
+
python -m edata.cli update-custom-bill \
|
|
845
845
|
--cups ES0000000000000000XX \
|
|
846
846
|
--p1-kw-year-eur 30.67 \
|
|
847
847
|
--p2-kw-year-eur 1.42 \
|
|
@@ -17,7 +17,7 @@ app = typer.Typer()
|
|
|
17
17
|
|
|
18
18
|
|
|
19
19
|
@app.command()
|
|
20
|
-
def show_supplies(username: str):
|
|
20
|
+
def show_supplies(username: str) -> None:
|
|
21
21
|
"""Show supplies and contracts for a given datadis user."""
|
|
22
22
|
|
|
23
23
|
password = getpass()
|
|
@@ -28,7 +28,7 @@ def show_supplies(username: str):
|
|
|
28
28
|
typer.echo(supply.model_dump_json())
|
|
29
29
|
if supplies:
|
|
30
30
|
cups = supplies[0].cups
|
|
31
|
-
distributor = supplies[0].
|
|
31
|
+
distributor = supplies[0].distributor_code
|
|
32
32
|
contracts = connector.get_contract_detail(cups, distributor)
|
|
33
33
|
typer.echo("\nContracts:")
|
|
34
34
|
for contract in contracts:
|
|
@@ -41,7 +41,7 @@ async def _download_all(
|
|
|
41
41
|
nif: str,
|
|
42
42
|
cups: str,
|
|
43
43
|
authorized_nif: str | None = None,
|
|
44
|
-
):
|
|
44
|
+
) -> None:
|
|
45
45
|
"""Download all data for a given datadis account and CUPS."""
|
|
46
46
|
|
|
47
47
|
password = getpass()
|
|
@@ -63,7 +63,7 @@ def download_all(
|
|
|
63
63
|
nif: str,
|
|
64
64
|
cups: Annotated[str, typer.Option(help="The identifier of the Supply")],
|
|
65
65
|
authorized_nif: str | None = None,
|
|
66
|
-
):
|
|
66
|
+
) -> None:
|
|
67
67
|
"""Download all data for a given datadis account and CUPS."""
|
|
68
68
|
|
|
69
69
|
asyncio.run(_download_all(nif, cups, authorized_nif))
|
|
@@ -77,7 +77,7 @@ async def _update_custom_bill(
|
|
|
77
77
|
p2_kwh_eur: float,
|
|
78
78
|
p3_kwh_eur: float,
|
|
79
79
|
meter_month_eur: float,
|
|
80
|
-
):
|
|
80
|
+
) -> None:
|
|
81
81
|
"""Download all data for a given datadis account and CUPS."""
|
|
82
82
|
|
|
83
83
|
bs = BillService(cups, storage_path="./edata_cli")
|
|
@@ -105,7 +105,7 @@ def update_custom_bill(
|
|
|
105
105
|
p2_kwh_eur: Annotated[float, typer.Option(help="Price per kWh at P2 tariff")],
|
|
106
106
|
p3_kwh_eur: Annotated[float, typer.Option(help="Price per kWh at P3 tariff")],
|
|
107
107
|
meter_month_eur: Annotated[float, typer.Option(help="Monthly cost of the meter")],
|
|
108
|
-
):
|
|
108
|
+
) -> None:
|
|
109
109
|
"""Download all data for a given datadis account and CUPS."""
|
|
110
110
|
|
|
111
111
|
asyncio.run(
|
|
@@ -121,7 +121,7 @@ def update_custom_bill(
|
|
|
121
121
|
)
|
|
122
122
|
|
|
123
123
|
|
|
124
|
-
async def _update_pvpc_bill(cups: str):
|
|
124
|
+
async def _update_pvpc_bill(cups: str) -> None:
|
|
125
125
|
"""Download all data for a given datadis account and CUPS."""
|
|
126
126
|
|
|
127
127
|
bs = BillService(cups, storage_path="./edata_cli")
|
|
@@ -131,7 +131,7 @@ async def _update_pvpc_bill(cups: str):
|
|
|
131
131
|
@app.command()
|
|
132
132
|
def update_pvpc_bill(
|
|
133
133
|
cups: Annotated[str, typer.Option(help="The identifier of the Supply")],
|
|
134
|
-
):
|
|
134
|
+
) -> None:
|
|
135
135
|
"""Download all data for a given datadis account and CUPS."""
|
|
136
136
|
|
|
137
137
|
asyncio.run(
|
|
@@ -43,7 +43,7 @@ def get_tariff(dt: datetime) -> int:
|
|
|
43
43
|
return 0
|
|
44
44
|
|
|
45
45
|
|
|
46
|
-
def get_contract_for_dt(contracts: list[Contract], date: datetime):
|
|
46
|
+
def get_contract_for_dt(contracts: list[Contract], date: datetime) -> Contract | None:
|
|
47
47
|
"""Return the active contract for a provided datetime."""
|
|
48
48
|
|
|
49
49
|
for contract in contracts:
|
|
@@ -49,12 +49,12 @@ class EdataDB:
|
|
|
49
49
|
return cls._instance
|
|
50
50
|
|
|
51
51
|
@property
|
|
52
|
-
def engine(self):
|
|
52
|
+
def engine(self) -> AsyncEngine | None:
|
|
53
53
|
"""Return the async database engine."""
|
|
54
54
|
|
|
55
55
|
return self._engine
|
|
56
56
|
|
|
57
|
-
async def _ensure_tables(self):
|
|
57
|
+
async def _ensure_tables(self) -> None:
|
|
58
58
|
"""Create tables if not already created (lazy init)."""
|
|
59
59
|
|
|
60
60
|
if self._tables_initialized:
|
|
@@ -84,11 +84,11 @@ class EdataDB:
|
|
|
84
84
|
self,
|
|
85
85
|
session: AsyncSession,
|
|
86
86
|
query: SelectOfScalar,
|
|
87
|
-
data,
|
|
87
|
+
data: typing.Any,
|
|
88
88
|
commit: bool = True,
|
|
89
89
|
overrides: dict[str, typing.Any] | None = None,
|
|
90
90
|
) -> T | None: # type: ignore
|
|
91
|
-
"""
|
|
91
|
+
"""Update a single record in the database."""
|
|
92
92
|
|
|
93
93
|
result = await session.exec(query)
|
|
94
94
|
existing = result.first()
|
|
@@ -240,7 +240,7 @@ class EdataDB:
|
|
|
240
240
|
session, q.get_energy(cups, energy.datetime), record
|
|
241
241
|
)
|
|
242
242
|
|
|
243
|
-
async def add_energy_list(self, cups: str, energy: list[Energy]):
|
|
243
|
+
async def add_energy_list(self, cups: str, energy: list[Energy]) -> None:
|
|
244
244
|
"""Add or update a list of energy records."""
|
|
245
245
|
|
|
246
246
|
await self._ensure_tables()
|
|
@@ -264,7 +264,7 @@ class EdataDB:
|
|
|
264
264
|
session, q.get_power(cups, power.datetime), record
|
|
265
265
|
)
|
|
266
266
|
|
|
267
|
-
async def add_power_list(self, cups: str, power: list[Power]):
|
|
267
|
+
async def add_power_list(self, cups: str, power: list[Power]) -> None:
|
|
268
268
|
"""Add or update a list of power records."""
|
|
269
269
|
|
|
270
270
|
await self._ensure_tables()
|
|
@@ -285,7 +285,7 @@ class EdataDB:
|
|
|
285
285
|
session, q.get_pvpc(pvpc.datetime), record
|
|
286
286
|
)
|
|
287
287
|
|
|
288
|
-
async def add_pvpc_list(self, pvpc: list[EnergyPrice]):
|
|
288
|
+
async def add_pvpc_list(self, pvpc: list[EnergyPrice]) -> None:
|
|
289
289
|
"""Add or update a list of pvpc records."""
|
|
290
290
|
|
|
291
291
|
await self._ensure_tables()
|
|
@@ -351,7 +351,7 @@ class EdataDB:
|
|
|
351
351
|
confhash: str,
|
|
352
352
|
complete: bool,
|
|
353
353
|
bill: list[Bill],
|
|
354
|
-
):
|
|
354
|
+
) -> None:
|
|
355
355
|
"""Add or update a list of bill records."""
|
|
356
356
|
|
|
357
357
|
await self._ensure_tables()
|
|
@@ -374,7 +374,7 @@ class EdataDB:
|
|
|
374
374
|
session, queries, items, override=["complete", "confhash"]
|
|
375
375
|
)
|
|
376
376
|
|
|
377
|
-
async def list_supplies(self):
|
|
377
|
+
async def list_supplies(self) -> typing.Sequence[SupplyModel]:
|
|
378
378
|
"""List all supply records."""
|
|
379
379
|
|
|
380
380
|
await self._ensure_tables()
|
|
@@ -382,7 +382,9 @@ class EdataDB:
|
|
|
382
382
|
result = await session.exec(q.list_supply())
|
|
383
383
|
return result.all()
|
|
384
384
|
|
|
385
|
-
async def list_contracts(
|
|
385
|
+
async def list_contracts(
|
|
386
|
+
self, cups: str | None = None
|
|
387
|
+
) -> typing.Sequence[ContractModel]:
|
|
386
388
|
"""List all contract records."""
|
|
387
389
|
|
|
388
390
|
await self._ensure_tables()
|
|
@@ -395,7 +397,7 @@ class EdataDB:
|
|
|
395
397
|
cups: str,
|
|
396
398
|
date_from: datetime | None = None,
|
|
397
399
|
date_to: datetime | None = None,
|
|
398
|
-
):
|
|
400
|
+
) -> typing.Sequence[EnergyModel]:
|
|
399
401
|
"""List energy records."""
|
|
400
402
|
|
|
401
403
|
await self._ensure_tables()
|
|
@@ -408,7 +410,7 @@ class EdataDB:
|
|
|
408
410
|
cups: str,
|
|
409
411
|
date_from: datetime | None = None,
|
|
410
412
|
date_to: datetime | None = None,
|
|
411
|
-
):
|
|
413
|
+
) -> typing.Sequence[PowerModel]:
|
|
412
414
|
"""List power records."""
|
|
413
415
|
|
|
414
416
|
await self._ensure_tables()
|
|
@@ -420,7 +422,7 @@ class EdataDB:
|
|
|
420
422
|
self,
|
|
421
423
|
date_from: datetime | None = None,
|
|
422
424
|
date_to: datetime | None = None,
|
|
423
|
-
):
|
|
425
|
+
) -> typing.Sequence[PVPCModel]:
|
|
424
426
|
"""List pvpc records."""
|
|
425
427
|
|
|
426
428
|
await self._ensure_tables()
|
|
@@ -435,7 +437,7 @@ class EdataDB:
|
|
|
435
437
|
date_from: datetime | None = None,
|
|
436
438
|
date_to: datetime | None = None,
|
|
437
439
|
complete: bool | None = None,
|
|
438
|
-
):
|
|
440
|
+
) -> typing.Sequence[StatisticsModel]:
|
|
439
441
|
"""List statistics records filtered by type ('day' or 'month') and date range."""
|
|
440
442
|
|
|
441
443
|
await self._ensure_tables()
|
|
@@ -452,7 +454,7 @@ class EdataDB:
|
|
|
452
454
|
date_from: datetime | None = None,
|
|
453
455
|
date_to: datetime | None = None,
|
|
454
456
|
complete: bool | None = None,
|
|
455
|
-
):
|
|
457
|
+
) -> typing.Sequence[BillModel]:
|
|
456
458
|
"""List bill records filtered by type ('hour', 'day' or 'month') and date range."""
|
|
457
459
|
|
|
458
460
|
await self._ensure_tables()
|
|
@@ -215,7 +215,9 @@ def list_pvpc(
|
|
|
215
215
|
return query
|
|
216
216
|
|
|
217
217
|
|
|
218
|
-
def get_bill(
|
|
218
|
+
def get_bill(
|
|
219
|
+
cups: str, type_: typing.Literal["hour", "day", "month"], datetime_: datetime | None
|
|
220
|
+
) -> SelectOfScalar[BillModel]:
|
|
219
221
|
"""Query that selects a bill."""
|
|
220
222
|
|
|
221
223
|
query = select(BillModel).where(BillModel.cups == cups)
|
|
@@ -7,10 +7,7 @@ T = TypeVar("T", bound=BaseModel)
|
|
|
7
7
|
|
|
8
8
|
|
|
9
9
|
class PydanticJSON(TypeDecorator):
|
|
10
|
-
"""
|
|
11
|
-
Tipo de SQLAlchemy para guardar modelos Pydantic como JSON.
|
|
12
|
-
Automáticamente serializa al guardar y deserializa al leer.
|
|
13
|
-
"""
|
|
10
|
+
"""SQLAlchemy type to guard Pydantic models as JSON."""
|
|
14
11
|
|
|
15
12
|
impl = JSON
|
|
16
13
|
cache_ok = True
|
|
@@ -20,6 +17,7 @@ class PydanticJSON(TypeDecorator):
|
|
|
20
17
|
self.pydantic_model = pydantic_model
|
|
21
18
|
|
|
22
19
|
def process_bind_param(self, value: T | None, dialect: Any) -> Any:
|
|
20
|
+
"""Process binding parameter."""
|
|
23
21
|
# Python -> Base de Datos
|
|
24
22
|
if value is None:
|
|
25
23
|
return None
|
|
@@ -27,6 +25,7 @@ class PydanticJSON(TypeDecorator):
|
|
|
27
25
|
return value.model_dump(mode="json")
|
|
28
26
|
|
|
29
27
|
def process_result_value(self, value: Any, dialect: Any) -> T | None:
|
|
28
|
+
"""Process result value."""
|
|
30
29
|
# Base de Datos -> Python
|
|
31
30
|
if value is None:
|
|
32
31
|
return None
|
|
@@ -6,15 +6,15 @@ from pydantic import BaseModel, Field
|
|
|
6
6
|
|
|
7
7
|
|
|
8
8
|
class EnergyPrice(BaseModel):
|
|
9
|
-
"""
|
|
9
|
+
"""Represent pricing data."""
|
|
10
10
|
|
|
11
11
|
datetime: datetime
|
|
12
|
-
|
|
12
|
+
value_eur_kwh: float
|
|
13
13
|
delta_h: float
|
|
14
14
|
|
|
15
15
|
|
|
16
16
|
class Bill(BaseModel):
|
|
17
|
-
"""
|
|
17
|
+
"""Represent a bill during a period."""
|
|
18
18
|
|
|
19
19
|
datetime: datetime
|
|
20
20
|
delta_h: float
|
|
@@ -26,7 +26,7 @@ class Bill(BaseModel):
|
|
|
26
26
|
|
|
27
27
|
|
|
28
28
|
class BillingRules(BaseModel):
|
|
29
|
-
"""
|
|
29
|
+
"""Represent a generic billing rule."""
|
|
30
30
|
|
|
31
31
|
p1_kw_year_eur: float
|
|
32
32
|
p2_kw_year_eur: float
|
|
@@ -50,7 +50,7 @@ class BillingRules(BaseModel):
|
|
|
50
50
|
|
|
51
51
|
|
|
52
52
|
class PVPCBillingRules(BillingRules):
|
|
53
|
-
"""
|
|
53
|
+
"""Represent a PVPC billing rule."""
|
|
54
54
|
|
|
55
55
|
p1_kw_year_eur: float = Field(default=30.67266)
|
|
56
56
|
p2_kw_year_eur: float = Field(default=1.4243591)
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
"""Models for telemetry data"""
|
|
2
|
+
|
|
3
|
+
from datetime import datetime
|
|
4
|
+
|
|
5
|
+
from pydantic import BaseModel, Field
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class Energy(BaseModel):
|
|
9
|
+
"""Represent energy consumption and/or surplus measurements."""
|
|
10
|
+
|
|
11
|
+
datetime: datetime
|
|
12
|
+
delta_h: float
|
|
13
|
+
consumption_kwh: float
|
|
14
|
+
surplus_kwh: float = Field(0)
|
|
15
|
+
generation_kwh: float = Field(0)
|
|
16
|
+
selfconsumption_kwh: float = Field(0)
|
|
17
|
+
real: bool
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
class Power(BaseModel):
|
|
21
|
+
"""Represent power measurements."""
|
|
22
|
+
|
|
23
|
+
datetime: datetime
|
|
24
|
+
value_kw: float
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
class Statistics(BaseModel):
|
|
28
|
+
"""Represent aggregated energy/surplus data."""
|
|
29
|
+
|
|
30
|
+
datetime: datetime
|
|
31
|
+
delta_h: float = Field(0)
|
|
32
|
+
consumption_kwh: float = Field(0)
|
|
33
|
+
consumption_by_tariff: list[float] = Field(default_factory=lambda: [0.0, 0.0, 0.0])
|
|
34
|
+
surplus_kwh: float = Field(0)
|
|
35
|
+
surplus_by_tariff: list[float] = Field(default_factory=lambda: [0.0, 0.0, 0.0])
|
|
36
|
+
generation_kwh: float = Field(0)
|
|
37
|
+
generation_by_tariff: list[float] = Field(default_factory=lambda: [0.0, 0.0, 0.0])
|
|
38
|
+
selfconsumption_kwh: float = Field(0)
|
|
39
|
+
selfconsumption_by_tariff: list[float] = Field(
|
|
40
|
+
default_factory=lambda: [0.0, 0.0, 0.0]
|
|
41
|
+
)
|
|
42
|
+
|
|
43
|
+
@property
|
|
44
|
+
def consumption_p1_kwh(self) -> float:
|
|
45
|
+
return self.consumption_by_tariff[0]
|
|
46
|
+
|
|
47
|
+
@property
|
|
48
|
+
def consumption_p2_kwh(self) -> float:
|
|
49
|
+
return self.consumption_by_tariff[1]
|
|
50
|
+
|
|
51
|
+
@property
|
|
52
|
+
def consumption_p3_kwh(self) -> float:
|
|
53
|
+
return self.consumption_by_tariff[2]
|
|
54
|
+
|
|
55
|
+
@property
|
|
56
|
+
def surplus_p1_kwh(self) -> float:
|
|
57
|
+
return self.surplus_by_tariff[0]
|
|
58
|
+
|
|
59
|
+
@property
|
|
60
|
+
def surplus_p2_kwh(self) -> float:
|
|
61
|
+
return self.surplus_by_tariff[1]
|
|
62
|
+
|
|
63
|
+
@property
|
|
64
|
+
def surplus_p3_kwh(self) -> float:
|
|
65
|
+
return self.surplus_by_tariff[2]
|
|
66
|
+
|
|
67
|
+
@property
|
|
68
|
+
def generation_p1_kwh(self) -> float:
|
|
69
|
+
return self.generation_by_tariff[0]
|
|
70
|
+
|
|
71
|
+
@property
|
|
72
|
+
def generation_p2_kwh(self) -> float:
|
|
73
|
+
return self.generation_by_tariff[1]
|
|
74
|
+
|
|
75
|
+
@property
|
|
76
|
+
def generation_p3_kwh(self) -> float:
|
|
77
|
+
return self.generation_by_tariff[2]
|
|
78
|
+
|
|
79
|
+
@property
|
|
80
|
+
def selfconsumption_p1_kwh(self) -> float:
|
|
81
|
+
return self.selfconsumption_by_tariff[0]
|
|
82
|
+
|
|
83
|
+
@property
|
|
84
|
+
def selfconsumption_p2_kwh(self) -> float:
|
|
85
|
+
return self.selfconsumption_by_tariff[1]
|
|
86
|
+
|
|
87
|
+
@property
|
|
88
|
+
def selfconsumption_p3_kwh(self) -> float:
|
|
89
|
+
return self.selfconsumption_by_tariff[2]
|
|
@@ -16,8 +16,8 @@ class Supply(BaseModel):
|
|
|
16
16
|
province: str | None
|
|
17
17
|
municipality: str | None
|
|
18
18
|
distributor: str | None
|
|
19
|
-
|
|
20
|
-
|
|
19
|
+
point_type: int
|
|
20
|
+
distributor_code: str
|
|
21
21
|
|
|
22
22
|
|
|
23
23
|
class Contract(BaseModel):
|
|
@@ -26,6 +26,15 @@ class Contract(BaseModel):
|
|
|
26
26
|
date_start: datetime
|
|
27
27
|
date_end: datetime
|
|
28
28
|
marketer: str
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
29
|
+
distributor_code: str
|
|
30
|
+
power: list[float]
|
|
31
|
+
|
|
32
|
+
@property
|
|
33
|
+
def power_p1(self) -> float | None:
|
|
34
|
+
"""Return power P1."""
|
|
35
|
+
return self.power[0] if len(self.power) > 0 else None
|
|
36
|
+
|
|
37
|
+
@property
|
|
38
|
+
def power_p2(self) -> float | None:
|
|
39
|
+
"""Return power P2."""
|
|
40
|
+
return self.power[1] if len(self.power) > 1 else None
|