pygazpar 1.3.0a24__tar.gz → 1.3.0b1__tar.gz

Sign up to get free protection for your applications and to get access to all the features.
Files changed (40) hide show
  1. {pygazpar-1.3.0a24 → pygazpar-1.3.0b1}/CHANGELOG.md +6 -0
  2. pygazpar-1.3.0a24/LICENSE.md → pygazpar-1.3.0b1/LICENSE +21 -21
  3. pygazpar-1.3.0b1/PKG-INFO +220 -0
  4. {pygazpar-1.3.0a24 → pygazpar-1.3.0b1}/README.md +7 -6
  5. pygazpar-1.3.0b1/pygazpar/__init__.py +10 -0
  6. pygazpar-1.3.0b1/pygazpar/__main__.py +81 -0
  7. {pygazpar-1.3.0a24 → pygazpar-1.3.0b1}/pygazpar/client.py +64 -59
  8. {pygazpar-1.3.0a24 → pygazpar-1.3.0b1}/pygazpar/datasource.py +177 -76
  9. {pygazpar-1.3.0a24 → pygazpar-1.3.0b1}/pygazpar/excelparser.py +15 -15
  10. {pygazpar-1.3.0a24 → pygazpar-1.3.0b1}/pygazpar/jsonparser.py +53 -50
  11. pygazpar-1.3.0b1/pygazpar/version.py +3 -0
  12. pygazpar-1.3.0b1/pyproject.toml +67 -0
  13. pygazpar-1.3.0a24/MANIFEST.in +0 -5
  14. pygazpar-1.3.0a24/PKG-INFO +0 -482
  15. pygazpar-1.3.0a24/pygazpar/__init__.py +0 -4
  16. pygazpar-1.3.0a24/pygazpar/__main__.py +0 -83
  17. pygazpar-1.3.0a24/pygazpar/version.py +0 -1
  18. pygazpar-1.3.0a24/pygazpar.egg-info/PKG-INFO +0 -482
  19. pygazpar-1.3.0a24/pygazpar.egg-info/SOURCES.txt +0 -34
  20. pygazpar-1.3.0a24/pygazpar.egg-info/dependency_links.txt +0 -1
  21. pygazpar-1.3.0a24/pygazpar.egg-info/entry_points.txt +0 -2
  22. pygazpar-1.3.0a24/pygazpar.egg-info/not-zip-safe +0 -1
  23. pygazpar-1.3.0a24/pygazpar.egg-info/requires.txt +0 -3
  24. pygazpar-1.3.0a24/pygazpar.egg-info/top_level.txt +0 -3
  25. pygazpar-1.3.0a24/samples/__init__.py +0 -0
  26. pygazpar-1.3.0a24/samples/excelSample.py +0 -31
  27. pygazpar-1.3.0a24/samples/jsonSample.py +0 -30
  28. pygazpar-1.3.0a24/samples/testSample.py +0 -18
  29. pygazpar-1.3.0a24/setup.cfg +0 -54
  30. pygazpar-1.3.0a24/setup.py +0 -3
  31. pygazpar-1.3.0a24/tests/__init__.py +0 -0
  32. pygazpar-1.3.0a24/tests/test_client.py +0 -159
  33. pygazpar-1.3.0a24/tests/test_datafileparser.py +0 -20
  34. pygazpar-1.3.0a24/tests/test_datasource.py +0 -166
  35. {pygazpar-1.3.0a24 → pygazpar-1.3.0b1}/pygazpar/enum.py +0 -0
  36. {pygazpar-1.3.0a24 → pygazpar-1.3.0b1}/pygazpar/resources/daily_data_sample.json +0 -0
  37. {pygazpar-1.3.0a24 → pygazpar-1.3.0b1}/pygazpar/resources/hourly_data_sample.json +0 -0
  38. {pygazpar-1.3.0a24 → pygazpar-1.3.0b1}/pygazpar/resources/monthly_data_sample.json +0 -0
  39. {pygazpar-1.3.0a24 → pygazpar-1.3.0b1}/pygazpar/resources/weekly_data_sample.json +0 -0
  40. {pygazpar-1.3.0a24 → pygazpar-1.3.0b1}/pygazpar/resources/yearly_data_sample.json +0 -0
@@ -4,6 +4,12 @@ All notable changes to this project will be documented in this file.
4
4
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
5
5
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
6
6
 
7
+ ## [1.3.0] - 2025-02-08
8
+
9
+ ### Changed
10
+
11
+ [#85](https://github.com/ssenart/PyGazpar/issues/85) : Move to Poetry dependency/package management tool.
12
+
7
13
  ## [1.2.8](https://github.com/ssenart/PyGazpar/compare/1.2.8...1.2.7) - 2025-01-11
8
14
 
9
15
  ### Added
@@ -1,21 +1,21 @@
1
- MIT License
2
-
3
- Copyright (c) 2019 Stéphane Senart
4
-
5
- Permission is hereby granted, free of charge, to any person obtaining a copy
6
- of this software and associated documentation files (the "Software"), to deal
7
- in the Software without restriction, including without limitation the rights
8
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
- copies of the Software, and to permit persons to whom the Software is
10
- furnished to do so, subject to the following conditions:
11
-
12
- The above copyright notice and this permission notice shall be included in all
13
- copies or substantial portions of the Software.
14
-
15
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
- SOFTWARE.
1
+ MIT License
2
+
3
+ Copyright (c) 2025 Stéphane Senart
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,220 @@
1
+ Metadata-Version: 2.3
2
+ Name: pygazpar
3
+ Version: 1.3.0b1
4
+ Summary: Python library to download gas consumption from a GrDF (French Gas Company) account
5
+ License: MIT License
6
+
7
+ Copyright (c) 2025 Stéphane Senart
8
+
9
+ Permission is hereby granted, free of charge, to any person obtaining a copy
10
+ of this software and associated documentation files (the "Software"), to deal
11
+ in the Software without restriction, including without limitation the rights
12
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
13
+ copies of the Software, and to permit persons to whom the Software is
14
+ furnished to do so, subject to the following conditions:
15
+
16
+ The above copyright notice and this permission notice shall be included in all
17
+ copies or substantial portions of the Software.
18
+
19
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
25
+ SOFTWARE.
26
+ Author: Stéphane Senart
27
+ Requires-Python: >=3.9
28
+ Classifier: Programming Language :: Python :: 3.9
29
+ Classifier: Programming Language :: Python :: 3.10
30
+ Classifier: Programming Language :: Python :: 3.11
31
+ Classifier: Programming Language :: Python :: 3.12
32
+ Classifier: Programming Language :: Python :: 3.13
33
+ Requires-Dist: openpyxl (>=3.1.5,<4.0.0)
34
+ Requires-Dist: pandas (>=2.2.3,<3.0.0)
35
+ Requires-Dist: requests (>=2.32.3,<3.0.0)
36
+ Description-Content-Type: text/markdown
37
+
38
+ # PyGazpar
39
+
40
+ ## $\text{\color{green}{!!! This library is working again. CAPTCHA has been removed !!!}}$
41
+
42
+ PyGazpar is a Python library for getting natural gas consumption from GrDF French provider.
43
+
44
+ Their natural gas meter is called Gazpar. It is wireless and transmit the gas consumption once per day.
45
+
46
+ All consumption data is available on the client account at GrDF Web Site (https://monespace.grdf.fr).
47
+
48
+ PyGazpar automatically goes through the Web Site and download the consumption data, and make it available in a Python structure.
49
+
50
+ ## Installation
51
+
52
+ ### Requirements
53
+ PyGazpar does not require Selenium and corresponding geckodriver to work.
54
+
55
+ With the new GrDF web site, it is possible to load the consumption data far easily than before.
56
+
57
+ PyGazpar uses [Poetry](https://python-poetry.org/) for dependency and package management.
58
+
59
+ ### Create your virtual environment
60
+
61
+ ```bash
62
+ $ cd /path/to/my_project_folder/
63
+
64
+ $ poetry install
65
+ ```
66
+
67
+ ### PyGazpar installation
68
+
69
+ Use the package manager [pip](https://pip.pypa.io/en/stable/) to install PyGazpar.
70
+
71
+ ```bash
72
+ pip install pygazpar
73
+ ```
74
+
75
+ You can also download the source code and install it manually.
76
+ ```bash
77
+ cd /path/to/pygazpar/
78
+
79
+ $ poetry install
80
+ ```
81
+
82
+ ## Usage
83
+
84
+ #### Command line:
85
+
86
+ 1. Standard usage (using Json GrDF API).
87
+
88
+ ```bash
89
+ $ pygazpar -u 'your login' -p 'your password' -c 'your PCE identifier' --datasource 'json'
90
+ ```
91
+
92
+ 2. Alternate usage (using Excel GrDF document).
93
+
94
+ ```bash
95
+ $ pygazpar -u 'your login' -p 'your password' -c 'your PCE identifier' -t 'temporary directory where to store Excel file (ex: /tmp)' --datasource 'excel'
96
+ ```
97
+
98
+ 3. Test usage (using local static data files, do not connect to GrDF site).
99
+
100
+ ```bash
101
+ $ pygazpar -u 'your login' -p 'your password' -c 'your PCE identifier' --datasource 'test'
102
+ ```
103
+
104
+ #### Library:
105
+
106
+ 1. Standard usage (using Json GrDF API).
107
+
108
+ ```python
109
+ import pygazpar
110
+
111
+ client = pygazpar.Client(pygazpar.JsonWebDataSource(
112
+ username='your login',
113
+ password='your password')
114
+ )
115
+
116
+ data = client.loadSince(pceIdentifier='your PCE identifier',
117
+ lastNDays=60,
118
+ frequencies=[pygazpar.Frequency.DAILY, pygazpar.Frequency.MONTHLY])
119
+ ```
120
+ See [samples/jsonSample.py](samples/jsonSample.py) file for the full example.
121
+
122
+ 2. Alternate usage (using Excel GrDF document).
123
+
124
+ ```python
125
+ import pygazpar
126
+
127
+ client = pygazpar.Client(pygazpar.ExcelWebDataSource(
128
+ username='your login',
129
+ password='your password')
130
+ )
131
+
132
+ data = client.loadSince(pceIdentifier='your PCE identifier',
133
+ lastNDays=60,
134
+ frequencies=[pygazpar.Frequency.DAILY, pygazpar.Frequency.MONTHLY])
135
+ ```
136
+ See [samples/excelSample.py](samples/jsonSample.py) file for the full example.
137
+
138
+ 3. Test usage (using local static data files, do not connect to GrDF site).
139
+
140
+ ```python
141
+ import pygazpar
142
+
143
+ client = pygazpar.Client(pygazpar.TestDataSource())
144
+
145
+ data = client.loadSince(pceIdentifier='your PCE identifier',
146
+ lastNDays=10,
147
+ frequencies=[pygazpar.Frequency.DAILY, Frequency.MONTHLY])
148
+ ```
149
+ See [samples/testSample.py](samples/jsonSample.py) file for the full example.
150
+
151
+ #### Output:
152
+
153
+ ```json
154
+ data =>
155
+ {
156
+ "daily": [
157
+ {
158
+ "time_period": "13/10/2022",
159
+ "start_index_m3": 15724,
160
+ "end_index_m3": 15725,
161
+ "volume_m3": 2,
162
+ "energy_kwh": 17,
163
+ "converter_factor_kwh/m3": 11.16,
164
+ "temperature_degC": null,
165
+ "type": "Mesur\u00e9",
166
+ "timestamp": "2022-12-13T23:58:35.606763"
167
+ },
168
+ ...
169
+ {
170
+ "time_period": "11/12/2022",
171
+ "start_index_m3": 16081,
172
+ "end_index_m3": 16098,
173
+ "volume_m3": 18,
174
+ "energy_kwh": 201,
175
+ "converter_factor_kwh/m3": 11.27,
176
+ "temperature_degC": -1.47,
177
+ "type": "Mesur\u00e9",
178
+ "timestamp": "2022-12-13T23:58:35.606763"
179
+ }
180
+ ],
181
+ "monthly": [
182
+ {
183
+ "time_period": "Novembre 2022",
184
+ "start_index_m3": 15750,
185
+ "end_index_m3": 15950,
186
+ "volume_m3": 204,
187
+ "energy_kwh": 2227,
188
+ "timestamp": "2022-12-13T23:58:35.606763"
189
+ },
190
+ {
191
+ "time_period": "D\u00e9cembre 2022",
192
+ "start_index_m3": 15950,
193
+ "end_index_m3": 16098,
194
+ "volume_m3": 148,
195
+ "energy_kwh": 1664,
196
+ "timestamp": "2022-12-13T23:58:35.606763"
197
+ }
198
+ ]
199
+ }
200
+ ```
201
+
202
+ ## Limitation
203
+ PyGazpar relies on how GrDF Web Site is built.
204
+
205
+ Any change in the Web site may break this library.
206
+
207
+ We expect in close Future that GrDF makes available an open API from which we can get safely their data.
208
+
209
+ ## Contributing
210
+ Pull requests are welcome. For major changes, please open an issue first to discuss what you would like to change.
211
+
212
+ Please make sure to update tests as appropriate.
213
+
214
+ ## License
215
+ [MIT](https://choosealicense.com/licenses/mit/)
216
+
217
+ ## Project status
218
+ PyGazpar has been initiated for integration with [Home Assistant](https://www.home-assistant.io/).
219
+
220
+ Corresponding Home Assistant integration custom component is available [here](https://github.com/ssenart/home-assistant-gazpar).
@@ -17,20 +17,20 @@ PyGazpar does not require Selenium and corresponding geckodriver to work.
17
17
 
18
18
  With the new GrDF web site, it is possible to load the consumption data far easily than before.
19
19
 
20
+ PyGazpar uses [Poetry](https://python-poetry.org/) for dependency and package management.
21
+
20
22
  ### Create your virtual environment
23
+
21
24
  ```bash
22
25
  $ cd /path/to/my_project_folder/
23
26
 
24
- $ python -m venv .venv
27
+ $ poetry install
25
28
  ```
26
29
 
27
30
  ### PyGazpar installation
28
- Activate your virtual environment.
29
- ```bash
30
- source .venv/bin/activate
31
- ```
32
31
 
33
32
  Use the package manager [pip](https://pip.pypa.io/en/stable/) to install PyGazpar.
33
+
34
34
  ```bash
35
35
  pip install pygazpar
36
36
  ```
@@ -38,7 +38,8 @@ pip install pygazpar
38
38
  You can also download the source code and install it manually.
39
39
  ```bash
40
40
  cd /path/to/pygazpar/
41
- python setup.py install
41
+
42
+ $ poetry install
42
43
  ```
43
44
 
44
45
  ## Usage
@@ -0,0 +1,10 @@
1
+ from pygazpar.client import Client # noqa: F401
2
+ from pygazpar.datasource import ( # noqa: F401
3
+ ExcelFileDataSource,
4
+ ExcelWebDataSource,
5
+ JsonFileDataSource,
6
+ JsonWebDataSource,
7
+ TestDataSource,
8
+ )
9
+ from pygazpar.enum import Frequency, PropertyName # noqa: F401
10
+ from pygazpar.version import __version__ # noqa: F401
@@ -0,0 +1,81 @@
1
+ import argparse
2
+ import json
3
+ import logging
4
+ import os
5
+ import sys
6
+ import traceback
7
+
8
+ import pygazpar
9
+
10
+
11
+ def main():
12
+ """Main function"""
13
+ parser = argparse.ArgumentParser()
14
+ parser.add_argument("-v", "--version", action="version", version=f"PyGazpar {pygazpar.__version__}")
15
+ parser.add_argument("-u", "--username", required=True, help="GRDF username (email)")
16
+ parser.add_argument("-p", "--password", required=True, help="GRDF password")
17
+ parser.add_argument("-c", "--pce", required=True, help="GRDF PCE identifier")
18
+ parser.add_argument("-t", "--tmpdir", required=False, default="/tmp", help="tmp directory (default is /tmp)")
19
+ parser.add_argument(
20
+ "-f",
21
+ "--frequency",
22
+ required=False,
23
+ type=lambda frequency: pygazpar.Frequency[frequency],
24
+ choices=list(pygazpar.Frequency),
25
+ default="DAILY",
26
+ help="Meter reading frequency (DAILY, WEEKLY, MONTHLY, YEARLY)",
27
+ )
28
+ parser.add_argument(
29
+ "-d",
30
+ "--lastNDays",
31
+ required=False,
32
+ type=int,
33
+ default=365,
34
+ help="Get only the last N days of records (default: 365 days)",
35
+ )
36
+ parser.add_argument("--datasource", required=False, default="json", help="Datasource: json | excel | test")
37
+
38
+ args = parser.parse_args()
39
+
40
+ # We create the tmp directory if not already exists.
41
+ if not os.path.exists(args.tmpdir):
42
+ os.mkdir(args.tmpdir)
43
+
44
+ # We remove the pygazpar log file.
45
+ pygazparLogFile = f"{args.tmpdir}/pygazpar.log"
46
+ if os.path.isfile(pygazparLogFile):
47
+ os.remove(pygazparLogFile)
48
+
49
+ # Setup logging.
50
+ logging.basicConfig(
51
+ filename=f"{pygazparLogFile}", level=logging.DEBUG, format="%(asctime)s %(levelname)s [%(name)s] %(message)s"
52
+ )
53
+
54
+ logging.info(f"PyGazpar {pygazpar.__version__}")
55
+ logging.info(f"--tmpdir {args.tmpdir}")
56
+ logging.info(f"--frequency {args.frequency}")
57
+ logging.info(f"--lastNDays {args.lastNDays}")
58
+ logging.info(f"--datasource {bool(args.datasource)}")
59
+
60
+ if args.datasource == "json":
61
+ client = pygazpar.Client(pygazpar.JsonWebDataSource(args.username, args.password))
62
+ elif args.datasource == "excel":
63
+ client = pygazpar.Client(pygazpar.ExcelWebDataSource(args.username, args.password, args.tmpdir))
64
+ elif args.datasource == "test":
65
+ client = pygazpar.Client(pygazpar.TestDataSource())
66
+ else:
67
+ raise ValueError("Invalid datasource: (json | excel | test) is expected")
68
+
69
+ try:
70
+ data = client.loadSince(args.pce, int(args.lastNDays), [args.frequency])
71
+ except BaseException: # pylint: disable=broad-except
72
+ print("An error occured while querying PyGazpar library : %s", traceback.format_exc())
73
+ return 1
74
+
75
+ print(json.dumps(data, indent=2))
76
+
77
+ return 0
78
+
79
+
80
+ if __name__ == "__main__":
81
+ sys.exit(main())
@@ -1,59 +1,64 @@
1
- import logging
2
- from datetime import date, timedelta
3
- from pygazpar.enum import Frequency
4
- from pygazpar.datasource import IDataSource, MeterReadingsByFrequency
5
- from typing import List, Optional
6
-
7
- AUTH_NONCE_URL = "https://monespace.grdf.fr/client/particulier/accueil"
8
- LOGIN_URL = "https://login.monespace.grdf.fr/sofit-account-api/api/v1/auth"
9
- LOGIN_HEADER = {"domain": "grdf.fr"}
10
- LOGIN_PAYLOAD = """{{
11
- "email": "{0}",
12
- "password": "{1}",
13
- "capp": "meg",
14
- "goto": "https://sofa-connexion.grdf.fr:443/openam/oauth2/externeGrdf/authorize?response_type=code&scope=openid%20profile%20email%20infotravaux%20%2Fv1%2Faccreditation%20%2Fv1%2Faccreditations%20%2Fdigiconso%2Fv1%20%2Fdigiconso%2Fv1%2Fconsommations%20new_meg&client_id=prod_espaceclient&state=0&redirect_uri=https%3A%2F%2Fmonespace.grdf.fr%2F_codexch&nonce={2}&by_pass_okta=1&capp=meg"}}"""
15
- DATA_URL = "https://monespace.grdf.fr/api/e-conso/pce/consommation/informatives/telecharger?dateDebut={1}&dateFin={2}&frequence={0}&pceList%5B%5D={3}"
16
- DATA_FILENAME = 'Donnees_informatives_*.xlsx'
17
-
18
- DEFAULT_TMP_DIRECTORY = '/tmp'
19
- DEFAULT_LAST_N_DAYS = 365
20
-
21
-
22
- Logger = logging.getLogger(__name__)
23
-
24
-
25
- # ------------------------------------------------------------------------------------------------------------
26
- class Client:
27
-
28
- # ------------------------------------------------------
29
- def __init__(self, dataSource: IDataSource):
30
- self.__dataSource = dataSource
31
-
32
- # ------------------------------------------------------
33
- def loadSince(self, pceIdentifier: str, lastNDays: int = DEFAULT_LAST_N_DAYS, frequencies: Optional[List[Frequency]] = None) -> MeterReadingsByFrequency:
34
-
35
- try:
36
- endDate = date.today()
37
- startDate = endDate + timedelta(days=-lastNDays)
38
-
39
- res = self.loadDateRange(pceIdentifier, startDate, endDate, frequencies)
40
- except Exception:
41
- Logger.error("An unexpected error occured while loading the data", exc_info=True)
42
- raise
43
-
44
- return res
45
-
46
- # ------------------------------------------------------
47
- def loadDateRange(self, pceIdentifier: str, startDate: date, endDate: date, frequencies: Optional[List[Frequency]] = None) -> MeterReadingsByFrequency:
48
-
49
- Logger.debug("Start loading the data...")
50
-
51
- try:
52
- res = self.__dataSource.load(pceIdentifier, startDate, endDate, frequencies)
53
-
54
- Logger.debug("The data load terminates normally")
55
- except Exception:
56
- Logger.error("An unexpected error occured while loading the data", exc_info=True)
57
- raise
58
-
59
- return res
1
+ import logging
2
+ from datetime import date, timedelta
3
+ from typing import List, Optional
4
+
5
+ from pygazpar.datasource import IDataSource, MeterReadingsByFrequency
6
+ from pygazpar.enum import Frequency
7
+
8
+ AUTH_NONCE_URL = "https://monespace.grdf.fr/client/particulier/accueil"
9
+ LOGIN_URL = "https://login.monespace.grdf.fr/sofit-account-api/api/v1/auth"
10
+ LOGIN_HEADER = {"domain": "grdf.fr"}
11
+ LOGIN_PAYLOAD = """{{
12
+ "email": "{0}",
13
+ "password": "{1}",
14
+ "capp": "meg",
15
+ "goto": "https://sofa-connexion.grdf.fr:443/openam/oauth2/externeGrdf/authorize?response_type=code&scope=openid%20profile%20email%20infotravaux%20%2Fv1%2Faccreditation%20%2Fv1%2Faccreditations%20%2Fdigiconso%2Fv1%20%2Fdigiconso%2Fv1%2Fconsommations%20new_meg&client_id=prod_espaceclient&state=0&redirect_uri=https%3A%2F%2Fmonespace.grdf.fr%2F_codexch&nonce={2}&by_pass_okta=1&capp=meg"}}"""
16
+ DATA_URL = "https://monespace.grdf.fr/api/e-conso/pce/consommation/informatives/telecharger?dateDebut={1}&dateFin={2}&frequence={0}&pceList%5B%5D={3}"
17
+ DATA_FILENAME = "Donnees_informatives_*.xlsx"
18
+
19
+ DEFAULT_TMP_DIRECTORY = "/tmp"
20
+ DEFAULT_LAST_N_DAYS = 365
21
+
22
+
23
+ Logger = logging.getLogger(__name__)
24
+
25
+
26
+ # ------------------------------------------------------------------------------------------------------------
27
+ class Client:
28
+
29
+ # ------------------------------------------------------
30
+ def __init__(self, dataSource: IDataSource):
31
+ self.__dataSource = dataSource
32
+
33
+ # ------------------------------------------------------
34
+ def loadSince(
35
+ self, pceIdentifier: str, lastNDays: int = DEFAULT_LAST_N_DAYS, frequencies: Optional[List[Frequency]] = None
36
+ ) -> MeterReadingsByFrequency:
37
+
38
+ try:
39
+ endDate = date.today()
40
+ startDate = endDate + timedelta(days=-lastNDays)
41
+
42
+ res = self.loadDateRange(pceIdentifier, startDate, endDate, frequencies)
43
+ except Exception:
44
+ Logger.error("An unexpected error occured while loading the data", exc_info=True)
45
+ raise
46
+
47
+ return res
48
+
49
+ # ------------------------------------------------------
50
+ def loadDateRange(
51
+ self, pceIdentifier: str, startDate: date, endDate: date, frequencies: Optional[List[Frequency]] = None
52
+ ) -> MeterReadingsByFrequency:
53
+
54
+ Logger.debug("Start loading the data...")
55
+
56
+ try:
57
+ res = self.__dataSource.load(pceIdentifier, startDate, endDate, frequencies)
58
+
59
+ Logger.debug("The data load terminates normally")
60
+ except Exception:
61
+ Logger.error("An unexpected error occured while loading the data", exc_info=True)
62
+ raise
63
+
64
+ return res