apyefa 0.0.7__py3-none-any.whl → 1.0.1__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 apyefa might be problematic. Click here for more details.
- apyefa/client.py +543 -52
- apyefa/commands/__init__.py +12 -0
- apyefa/commands/command.py +97 -53
- apyefa/commands/command_add_info.py +60 -0
- apyefa/commands/command_coord.py +45 -0
- apyefa/commands/command_departures.py +4 -5
- apyefa/commands/command_geoobject.py +42 -0
- apyefa/commands/command_line_list.py +46 -0
- apyefa/commands/command_line_stop.py +39 -0
- apyefa/commands/command_serving_lines.py +8 -18
- apyefa/commands/command_stop_finder.py +4 -6
- apyefa/commands/command_stop_list.py +48 -0
- apyefa/commands/command_system_info.py +3 -3
- apyefa/commands/command_trip.py +26 -5
- apyefa/data_classes.py +190 -65
- apyefa/helpers.py +61 -0
- apyefa-1.0.1.dist-info/METADATA +125 -0
- apyefa-1.0.1.dist-info/RECORD +27 -0
- {apyefa-0.0.7.dist-info → apyefa-1.0.1.dist-info}/WHEEL +1 -1
- apyefa-0.0.7.dist-info/METADATA +0 -430
- apyefa-0.0.7.dist-info/RECORD +0 -21
- {apyefa-0.0.7.dist-info → apyefa-1.0.1.dist-info}/LICENSE +0 -0
- {apyefa-0.0.7.dist-info → apyefa-1.0.1.dist-info}/top_level.txt +0 -0
apyefa/client.py
CHANGED
|
@@ -1,27 +1,39 @@
|
|
|
1
1
|
import logging
|
|
2
|
+
from datetime import date, datetime
|
|
3
|
+
from typing import Final
|
|
2
4
|
|
|
3
5
|
import aiohttp
|
|
4
6
|
|
|
5
7
|
from apyefa.commands import (
|
|
6
8
|
Command,
|
|
9
|
+
CommandCoord,
|
|
7
10
|
CommandDepartures,
|
|
11
|
+
CommandGeoObject,
|
|
12
|
+
CommandLineList,
|
|
13
|
+
CommandLineStop,
|
|
8
14
|
CommandServingLines,
|
|
9
15
|
CommandStopFinder,
|
|
16
|
+
CommandStopList,
|
|
10
17
|
CommandSystemInfo,
|
|
18
|
+
CommandTrip,
|
|
11
19
|
)
|
|
12
20
|
from apyefa.data_classes import (
|
|
13
21
|
CoordFormat,
|
|
14
22
|
Departure,
|
|
23
|
+
Jorney,
|
|
15
24
|
Line,
|
|
16
25
|
LineRequestType,
|
|
17
26
|
Location,
|
|
18
27
|
LocationFilter,
|
|
19
28
|
LocationType,
|
|
29
|
+
PointTypeFilter,
|
|
20
30
|
SystemInfo,
|
|
21
31
|
)
|
|
22
|
-
from apyefa.exceptions import EfaConnectionError
|
|
32
|
+
from apyefa.exceptions import EfaConnectionError, EfaFormatNotSupported
|
|
33
|
+
from apyefa.helpers import is_date
|
|
23
34
|
|
|
24
|
-
_LOGGER = logging.getLogger(__name__)
|
|
35
|
+
_LOGGER: Final = logging.getLogger(__name__)
|
|
36
|
+
QUERY_TIMEOUT: Final = 30 # seconds
|
|
25
37
|
|
|
26
38
|
|
|
27
39
|
class EfaClient:
|
|
@@ -32,57 +44,88 @@ class EfaClient:
|
|
|
32
44
|
async def __aexit__(self, *args, **kwargs):
|
|
33
45
|
await self._client_session.__aexit__(*args, **kwargs)
|
|
34
46
|
|
|
35
|
-
def __init__(self, url: str, debug: bool = False):
|
|
47
|
+
def __init__(self, url: str, debug: bool = False, format: str = "rapidJSON"):
|
|
36
48
|
"""Create a new instance of client.
|
|
37
49
|
|
|
38
50
|
Args:
|
|
39
|
-
url
|
|
51
|
+
url(str): EFA endpoint url
|
|
52
|
+
format(str, optional): Format of the response. Defaults to "rapidJSON".
|
|
40
53
|
|
|
41
54
|
Raises:
|
|
42
|
-
ValueError:
|
|
55
|
+
ValueError: If no url provided
|
|
56
|
+
EfaFormatNotSupported: If format is not supported
|
|
43
57
|
"""
|
|
44
58
|
if not url:
|
|
45
59
|
raise ValueError("No EFA endpoint url provided")
|
|
46
60
|
|
|
61
|
+
if format != "rapidJSON":
|
|
62
|
+
raise EfaFormatNotSupported(f"Format {format} is not supported")
|
|
63
|
+
|
|
47
64
|
self._debug: bool = debug
|
|
65
|
+
self._format: str = format
|
|
48
66
|
self._base_url: str = url if url.endswith("/") else f"{url}/"
|
|
49
67
|
|
|
50
68
|
async def info(self) -> SystemInfo:
|
|
51
|
-
"""Get system info
|
|
69
|
+
"""Get EFA endpoint system info.
|
|
52
70
|
|
|
53
71
|
Returns:
|
|
54
72
|
SystemInfo: info object
|
|
55
73
|
"""
|
|
56
74
|
_LOGGER.info("Request system info")
|
|
57
75
|
|
|
58
|
-
command = CommandSystemInfo()
|
|
76
|
+
command = CommandSystemInfo(self._format)
|
|
77
|
+
command.add_param("coordOutputFormat", CoordFormat.WGS84.value)
|
|
78
|
+
|
|
79
|
+
command.validate_params()
|
|
80
|
+
|
|
59
81
|
response = await self._run_query(self._build_url(command))
|
|
60
82
|
|
|
61
83
|
return command.parse(response)
|
|
62
84
|
|
|
63
85
|
async def locations_by_name(
|
|
64
|
-
self,
|
|
86
|
+
self,
|
|
87
|
+
name: str,
|
|
88
|
+
*,
|
|
89
|
+
filters: list[LocationFilter] = [],
|
|
90
|
+
limit: int = 30,
|
|
91
|
+
search_nearbly_stops: bool = False,
|
|
65
92
|
) -> list[Location]:
|
|
66
|
-
"""
|
|
93
|
+
"""
|
|
94
|
+
Asynchronously search for locations by name with optional filters and limits.
|
|
67
95
|
|
|
68
96
|
Args:
|
|
69
|
-
name (str):
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
97
|
+
name (str): The name or ID of the location to search for.
|
|
98
|
+
filters (list[LocationFilter], optional): A list of filters to apply to the search. Defaults to an empty list.
|
|
99
|
+
limit (int, optional): The maximum number of locations to return. Defaults to 30.
|
|
100
|
+
search_nearbly_stops (bool, optional): Whether to include nearby stops in the search. Defaults to False.
|
|
101
|
+
|
|
102
|
+
Raises:
|
|
103
|
+
ValueError: If no name is provided.
|
|
73
104
|
|
|
74
105
|
Returns:
|
|
75
|
-
list[Location]:
|
|
106
|
+
list[Location]: A list of locations matching the search criteria.
|
|
76
107
|
"""
|
|
77
108
|
_LOGGER.info(f"Request location search by name/id: {name}")
|
|
78
109
|
_LOGGER.debug(f"filters: {filters}")
|
|
79
110
|
_LOGGER.debug(f"limit: {limit}")
|
|
111
|
+
_LOGGER.debug(f"search_nearbly_stops: {search_nearbly_stops}")
|
|
112
|
+
|
|
113
|
+
if not name:
|
|
114
|
+
raise ValueError("No name provided")
|
|
80
115
|
|
|
81
|
-
command = CommandStopFinder(
|
|
116
|
+
command = CommandStopFinder(self._format)
|
|
117
|
+
|
|
118
|
+
command.add_param("locationServerActive", 1)
|
|
119
|
+
command.add_param("type_sf", "any")
|
|
120
|
+
command.add_param("name_sf", name)
|
|
121
|
+
command.add_param("coordOutputFormat", CoordFormat.WGS84.value)
|
|
122
|
+
command.add_param("doNotSearchForStops_sf", not search_nearbly_stops)
|
|
82
123
|
|
|
83
124
|
if filters:
|
|
84
125
|
command.add_param("anyObjFilter_sf", sum(filters))
|
|
85
126
|
|
|
127
|
+
command.validate_params()
|
|
128
|
+
|
|
86
129
|
response = await self._run_query(self._build_url(command))
|
|
87
130
|
|
|
88
131
|
return command.parse(response)[:limit]
|
|
@@ -91,94 +134,355 @@ class EfaClient:
|
|
|
91
134
|
self,
|
|
92
135
|
coord_x: float,
|
|
93
136
|
coord_y: float,
|
|
137
|
+
*,
|
|
94
138
|
format: CoordFormat = CoordFormat.WGS84,
|
|
95
139
|
limit: int = 10,
|
|
140
|
+
search_nearbly_stops: bool = False,
|
|
96
141
|
) -> Location:
|
|
97
|
-
"""
|
|
142
|
+
"""
|
|
143
|
+
Asynchronously fetches location information based on given coordinates.
|
|
98
144
|
|
|
99
145
|
Args:
|
|
100
|
-
coord_x (float): X coordinate
|
|
101
|
-
coord_y (float): Y coordinate
|
|
102
|
-
format (CoordFormat, optional):
|
|
103
|
-
limit (int, optional):
|
|
146
|
+
coord_x (float): The X coordinate (longitude).
|
|
147
|
+
coord_y (float): The Y coordinate (latitude).
|
|
148
|
+
format (CoordFormat, optional): The coordinate format. Defaults to CoordFormat.WGS84.
|
|
149
|
+
limit (int, optional): The maximum number of locations to return. Defaults to 10.
|
|
150
|
+
search_nearbly_stops (bool, optional): Whether to search for nearby stops. Defaults to False.
|
|
104
151
|
|
|
105
152
|
Returns:
|
|
106
|
-
Location:
|
|
153
|
+
Location: The location information based on the provided coordinates.
|
|
107
154
|
"""
|
|
108
155
|
_LOGGER.info("Request location search by coordinates")
|
|
109
156
|
_LOGGER.debug(f"coord_x: {coord_x}")
|
|
110
157
|
_LOGGER.debug(f"coord_y: {coord_y}")
|
|
111
158
|
_LOGGER.debug(f"format: {format}")
|
|
112
159
|
_LOGGER.debug(f"limit: {limit}")
|
|
160
|
+
_LOGGER.debug(f"search_nearbly_stops: {search_nearbly_stops}")
|
|
161
|
+
|
|
162
|
+
command = CommandStopFinder(self._format)
|
|
163
|
+
command.add_param("locationServerActive", 1)
|
|
164
|
+
command.add_param("type_sf", "coord")
|
|
165
|
+
command.add_param("name_sf", f"{coord_x}:{coord_y}:{format}")
|
|
166
|
+
command.add_param("coordOutputFormat", CoordFormat.WGS84.value)
|
|
167
|
+
command.add_param("doNotSearchForStops_sf", not search_nearbly_stops)
|
|
113
168
|
|
|
114
|
-
command
|
|
169
|
+
command.validate_params()
|
|
115
170
|
|
|
116
171
|
response = await self._run_query(self._build_url(command))
|
|
117
172
|
|
|
118
173
|
return command.parse(response)[:limit]
|
|
119
174
|
|
|
120
|
-
async def
|
|
121
|
-
|
|
175
|
+
async def list_lines(
|
|
176
|
+
self,
|
|
177
|
+
branch_code: str | None = None,
|
|
178
|
+
net_branch_code: str | None = None,
|
|
179
|
+
sub_network: str | None = None,
|
|
180
|
+
list_omc: str | None = None,
|
|
181
|
+
mixed_lines: bool = False,
|
|
182
|
+
merge_directions: bool = True,
|
|
183
|
+
req_types: list[LineRequestType] = [],
|
|
184
|
+
) -> list[Line]:
|
|
185
|
+
"""
|
|
186
|
+
Asynchronously retrieves a list of lines based on the provided parameters.
|
|
187
|
+
|
|
188
|
+
Args:
|
|
189
|
+
branch_code (str | None): The branch code to filter lines.
|
|
190
|
+
net_branch_code (str | None): The Network and optionally the code of the branch separated by colon.
|
|
191
|
+
sub_network (str | None): The sub-network to filter lines.
|
|
192
|
+
list_omc (str | None): The OMC(Open Method of Coordination) list to filter lines.
|
|
193
|
+
mixed_lines (bool): Activates the search of composed services. Defaults to False.
|
|
194
|
+
merge_directions (bool): Merges the inbound and outbound service. Thus only inbound services are listed. Defaults to True.
|
|
195
|
+
req_type (list[LineRequestType]): The request types to filter lines. Defaults to an empty list.
|
|
196
|
+
|
|
197
|
+
Returns:
|
|
198
|
+
list[Line]: A list of Line objects representing the lines.
|
|
199
|
+
"""
|
|
200
|
+
_LOGGER.info("Request lines")
|
|
201
|
+
_LOGGER.debug(f"branch_code: {branch_code}")
|
|
202
|
+
_LOGGER.debug(f"net_branch_code: {net_branch_code}")
|
|
203
|
+
_LOGGER.debug(f"sub_network: {sub_network}")
|
|
204
|
+
_LOGGER.debug(f"list_omc: {list_omc}")
|
|
205
|
+
_LOGGER.debug(f"mixed_lines: {mixed_lines}")
|
|
206
|
+
_LOGGER.debug(f"merge_directions: {merge_directions}")
|
|
207
|
+
_LOGGER.debug(f"req_types: {req_types}")
|
|
208
|
+
|
|
209
|
+
command = CommandLineList(self._format)
|
|
210
|
+
command.add_param("coordOutputFormat", CoordFormat.WGS84.value)
|
|
211
|
+
|
|
212
|
+
if branch_code:
|
|
213
|
+
command.add_param("lineListBranchCode", branch_code)
|
|
214
|
+
if net_branch_code:
|
|
215
|
+
command.add_param("lineListNetBranchCode", net_branch_code)
|
|
216
|
+
if sub_network:
|
|
217
|
+
command.add_param("lineListSubnetwork", sub_network)
|
|
218
|
+
if list_omc:
|
|
219
|
+
command.add_param("lineListOMC", list_omc)
|
|
220
|
+
if mixed_lines:
|
|
221
|
+
command.add_param("lineListMixedLines", mixed_lines)
|
|
222
|
+
if not merge_directions:
|
|
223
|
+
command.add_param("mergeDir", merge_directions)
|
|
224
|
+
if req_types:
|
|
225
|
+
command.add_param("lineReqType", sum(req_types))
|
|
226
|
+
|
|
227
|
+
command.validate_params()
|
|
228
|
+
|
|
229
|
+
response = await self._run_query(self._build_url(command))
|
|
230
|
+
|
|
231
|
+
return command.parse(response)
|
|
232
|
+
|
|
233
|
+
async def list_stops(
|
|
234
|
+
self,
|
|
235
|
+
omc: str | None = None,
|
|
236
|
+
place_id: str | None = None,
|
|
237
|
+
omc_place_id: str | None = None,
|
|
238
|
+
rtn: str | None = None,
|
|
239
|
+
sub_network: str | None = None,
|
|
240
|
+
from_stop: str | None = None,
|
|
241
|
+
to_stop: str | None = None,
|
|
242
|
+
serving_lines: bool = True,
|
|
243
|
+
serving_lines_mot_type: bool = True,
|
|
244
|
+
serving_lines_mot_types: bool = False,
|
|
245
|
+
tarif_zones: bool = True,
|
|
246
|
+
) -> list[Location]:
|
|
247
|
+
"""
|
|
248
|
+
Asynchronously retrieves a list of stops based on the provided parameters.
|
|
249
|
+
|
|
250
|
+
Args:
|
|
251
|
+
omc (str | None): Optional. The OMC (Operational Management Center) code.
|
|
252
|
+
place_id (str | None): Optional. ID of the place. Can be combined with `omc`.
|
|
253
|
+
omc_place_id (str | None): Optional. Combination of `omc` and `place_id`. OMC and ID of the place are separated by colon.
|
|
254
|
+
rtn (str | None): Optional. Only stops within the network given by parameter value.
|
|
255
|
+
sub_network (str | None): Optional. Only stops served by services from the network given by parameter value.
|
|
256
|
+
from_stop (str | None): Optional. Only stops with IDs within the intervall restricted by these parameters. Must be combined with `to_stop`.
|
|
257
|
+
to_stop (str | None): Optional. Only stops with IDs within the intervall restricted by these parameters. Must be combined with `from_stop`.
|
|
258
|
+
serving_lines (bool): Optional. Services of each stop. Default is True.
|
|
259
|
+
serving_lines_mot_type (bool): Optional. Mayor means of transport of each stop. The combination with `serving_lines_mot_types=True` is not possible. Default is True.
|
|
260
|
+
serving_lines_mot_types (bool): Optional. All means of transport of each stop. Separated by comma. The combination with `serving_lines_mot_type=True` is not possible. Default is False.
|
|
261
|
+
tarif_zones (bool): Optional. Tariff zone of each stop. Default is True.
|
|
262
|
+
|
|
263
|
+
Returns:
|
|
264
|
+
The parsed response from the command execution.
|
|
265
|
+
"""
|
|
266
|
+
command = CommandStopList(self._format)
|
|
267
|
+
command.add_param("coordOutputFormat", CoordFormat.WGS84.value)
|
|
268
|
+
|
|
269
|
+
if omc:
|
|
270
|
+
command.add_param("stopListOMC", omc)
|
|
271
|
+
if place_id:
|
|
272
|
+
command.add_param("stopListPlaceId", place_id)
|
|
273
|
+
if omc_place_id:
|
|
274
|
+
command.add_param("stopListOMCPlaceId", omc_place_id)
|
|
275
|
+
if rtn:
|
|
276
|
+
command.add_param("rTN", rtn)
|
|
277
|
+
if sub_network:
|
|
278
|
+
command.add_param("stopListSubnetwork", sub_network)
|
|
279
|
+
if from_stop:
|
|
280
|
+
command.add_param("fromstop", from_stop)
|
|
281
|
+
if to_stop:
|
|
282
|
+
command.add_param("tostop", to_stop)
|
|
283
|
+
|
|
284
|
+
command.add_param("servingLines", serving_lines)
|
|
285
|
+
command.add_param("servingLinesMOTType", serving_lines_mot_type)
|
|
286
|
+
command.add_param("servingLinesMOTTypes", serving_lines_mot_types)
|
|
287
|
+
command.add_param("tariffZones", tarif_zones)
|
|
288
|
+
|
|
289
|
+
command.validate_params()
|
|
290
|
+
|
|
291
|
+
response = await self._run_query(self._build_url(command))
|
|
292
|
+
|
|
293
|
+
return command.parse(response)
|
|
294
|
+
|
|
295
|
+
async def trip(
|
|
296
|
+
self,
|
|
297
|
+
origin: Location | str,
|
|
298
|
+
destination: Location | str,
|
|
299
|
+
trip_departure: bool = True,
|
|
300
|
+
trip_datetime: str | datetime | date | None = None,
|
|
301
|
+
) -> list[Jorney]:
|
|
302
|
+
"""
|
|
303
|
+
Asynchronously calculates a trip between an origin and a destination.
|
|
304
|
+
|
|
305
|
+
Args:
|
|
306
|
+
origin (Location | str): The starting point of the trip, either as a Location object or a string identifier.
|
|
307
|
+
destination (Location | str): The endpoint of the trip, either as a Location object or a string identifier.
|
|
308
|
+
trip_departure (bool, optional): Indicates whether the trip is based on departure time (True) or arrival time (False). Defaults to True.
|
|
309
|
+
trip_datetime (str | datetime | date | None, optional): The date and time of the departure/arrival. Can be a string, datetime object, date object, or None. Defaults to None.
|
|
310
|
+
|
|
311
|
+
Returns:
|
|
312
|
+
list[Jorney]: A list of Jorney objects representing the calculated trip.
|
|
313
|
+
|
|
314
|
+
Raises:
|
|
315
|
+
ValueError: If the parameters are invalid or the trip cannot be calculated.
|
|
316
|
+
"""
|
|
317
|
+
if isinstance(origin, Location):
|
|
318
|
+
origin = origin.id
|
|
319
|
+
|
|
320
|
+
if isinstance(destination, Location):
|
|
321
|
+
destination = destination.id
|
|
322
|
+
|
|
323
|
+
command = CommandTrip(self._format)
|
|
324
|
+
command.add_param("coordOutputFormat", CoordFormat.WGS84.value)
|
|
325
|
+
command.add_param("locationServerActive", True)
|
|
326
|
+
command.add_param("deleteAssignedStops_origin", True)
|
|
327
|
+
command.add_param("deleteAssignedStops_destination", True)
|
|
328
|
+
command.add_param("genC", False)
|
|
329
|
+
command.add_param("genP", False)
|
|
330
|
+
command.add_param("genMaps", False)
|
|
331
|
+
command.add_param("useRealtime", True)
|
|
332
|
+
command.add_param("useUT", True)
|
|
333
|
+
command.add_param("allInterchangesAsLegs", True)
|
|
334
|
+
command.add_param("calcOneDirection", True)
|
|
335
|
+
command.add_param("changeSpeed", "normal")
|
|
336
|
+
command.add_param("coordOutputDistance", True)
|
|
337
|
+
|
|
338
|
+
if trip_departure:
|
|
339
|
+
command.add_param("itdTripDateTimeDepArr", "dep")
|
|
340
|
+
else:
|
|
341
|
+
command.add_param("itdTripDateTimeDepArr", "arr")
|
|
342
|
+
|
|
343
|
+
if trip_datetime:
|
|
344
|
+
command.add_param_datetime(trip_datetime)
|
|
345
|
+
|
|
346
|
+
command.add_param("type_origin", "any")
|
|
347
|
+
command.add_param("name_origin", origin)
|
|
348
|
+
command.add_param("type_destination", "any")
|
|
349
|
+
command.add_param("name_destination", destination)
|
|
350
|
+
|
|
351
|
+
command.validate_params()
|
|
352
|
+
|
|
353
|
+
response = await self._run_query(self._build_url(command))
|
|
354
|
+
|
|
355
|
+
return command.parse(response)
|
|
122
356
|
|
|
123
357
|
async def departures_by_location(
|
|
124
358
|
self,
|
|
125
|
-
|
|
359
|
+
location: Location | str,
|
|
360
|
+
*,
|
|
126
361
|
limit=40,
|
|
127
|
-
|
|
362
|
+
arg_date: str | datetime | date | None = None,
|
|
363
|
+
realtime: bool = True,
|
|
128
364
|
) -> list[Departure]:
|
|
129
|
-
|
|
365
|
+
"""
|
|
366
|
+
Fetches departures for a given location.
|
|
367
|
+
|
|
368
|
+
Args:
|
|
369
|
+
location (Location | str): The location object or location ID as a string.
|
|
370
|
+
limit (int, optional): The maximum number of departures to return. Defaults to 40.
|
|
371
|
+
arg_date (str | datetime | date | None, optional): The date for which to fetch departures. Can be a string, datetime, date, or None. Defaults to None.
|
|
372
|
+
realtime (bool, optional): Whether to use real-time data. Defaults to True.
|
|
373
|
+
|
|
374
|
+
Returns:
|
|
375
|
+
list[Departure]: A list of Departure objects.
|
|
376
|
+
|
|
377
|
+
Raises:
|
|
378
|
+
ValueError: If no location is provided.
|
|
379
|
+
"""
|
|
380
|
+
_LOGGER.info(f"Request departures for location {location}")
|
|
130
381
|
_LOGGER.debug(f"limit: {limit}")
|
|
131
|
-
_LOGGER.debug(f"date: {
|
|
382
|
+
_LOGGER.debug(f"date: {arg_date}")
|
|
383
|
+
|
|
384
|
+
if not location:
|
|
385
|
+
raise ValueError("No location provided")
|
|
132
386
|
|
|
133
|
-
if isinstance(
|
|
134
|
-
|
|
387
|
+
if isinstance(location, Location):
|
|
388
|
+
location = location.id
|
|
135
389
|
|
|
136
|
-
command = CommandDepartures(
|
|
390
|
+
command = CommandDepartures(self._format)
|
|
137
391
|
|
|
138
392
|
# add parameters
|
|
139
|
-
command.add_param("
|
|
140
|
-
command.
|
|
393
|
+
command.add_param("locationServerActive", 1)
|
|
394
|
+
command.add_param("coordOutputFormat", CoordFormat.WGS84.value)
|
|
395
|
+
command.add_param("name_dm", location)
|
|
396
|
+
command.add_param("type_dm", "any")
|
|
397
|
+
|
|
398
|
+
if self._format == "rapidJSON":
|
|
399
|
+
command.add_param("mode", "direct")
|
|
400
|
+
command.add_param("useProxFootSearch", "0")
|
|
401
|
+
else:
|
|
402
|
+
command.add_param("mode", "any")
|
|
403
|
+
|
|
404
|
+
command.add_param("useAllStops", "1")
|
|
405
|
+
command.add_param("lsShowTrainsExplicit", "1")
|
|
406
|
+
command.add_param("useRealtime", realtime)
|
|
407
|
+
|
|
408
|
+
command.add_param_datetime(arg_date)
|
|
409
|
+
|
|
410
|
+
command.validate_params()
|
|
141
411
|
|
|
142
412
|
response = await self._run_query(self._build_url(command))
|
|
143
413
|
|
|
144
|
-
return command.parse(response)
|
|
414
|
+
return command.parse(response)[:limit]
|
|
145
415
|
|
|
146
|
-
async def lines_by_name(
|
|
147
|
-
|
|
416
|
+
async def lines_by_name(
|
|
417
|
+
self,
|
|
418
|
+
line: str,
|
|
419
|
+
*,
|
|
420
|
+
merge_directions: bool = False,
|
|
421
|
+
show_trains_explicit: bool = False,
|
|
422
|
+
) -> list[Line]:
|
|
423
|
+
"""
|
|
424
|
+
Asynchronously fetches lines by name.
|
|
148
425
|
|
|
149
426
|
Args:
|
|
150
|
-
line (str):
|
|
427
|
+
line (str): The name of the line to search for.
|
|
428
|
+
merge_directions (bool, optional): Whether to merge directions. Defaults to False.
|
|
429
|
+
show_trains_explicit (bool, optional): Whether to explicitly show trains. Defaults to False.
|
|
430
|
+
|
|
431
|
+
Raises:
|
|
432
|
+
ValueError: If no line is provided.
|
|
151
433
|
|
|
152
434
|
Returns:
|
|
153
|
-
list[
|
|
435
|
+
list[Line]: A list of Line objects matching the search criteria.
|
|
154
436
|
"""
|
|
155
437
|
_LOGGER.info("Request lines by name")
|
|
156
438
|
_LOGGER.debug(f"line:{line}")
|
|
157
439
|
|
|
158
|
-
|
|
440
|
+
if not line:
|
|
441
|
+
raise ValueError("No line provided")
|
|
442
|
+
|
|
443
|
+
command = CommandServingLines(self._format)
|
|
444
|
+
command.add_param("mode", "line")
|
|
445
|
+
command.add_param("lineName", line)
|
|
446
|
+
command.add_param("locationServerActive", 1)
|
|
447
|
+
command.add_param("mergeDir", merge_directions)
|
|
448
|
+
command.add_param("lsShowTrainsExplicit", show_trains_explicit)
|
|
449
|
+
command.add_param("coordOutputFormat", CoordFormat.WGS84.value)
|
|
450
|
+
|
|
451
|
+
command.validate_params()
|
|
159
452
|
|
|
160
453
|
response = await self._run_query(self._build_url(command))
|
|
161
454
|
|
|
162
455
|
return command.parse(response)
|
|
163
456
|
|
|
164
457
|
async def lines_by_location(
|
|
165
|
-
self,
|
|
458
|
+
self,
|
|
459
|
+
location: str | Location,
|
|
460
|
+
*,
|
|
461
|
+
req_types: list[LineRequestType] = [],
|
|
462
|
+
merge_directions: bool = False,
|
|
463
|
+
show_trains_explicit: bool = False,
|
|
166
464
|
) -> list[Line]:
|
|
167
|
-
"""
|
|
465
|
+
"""
|
|
466
|
+
Fetches lines by location.
|
|
168
467
|
|
|
169
468
|
Args:
|
|
170
|
-
location (str | Location): Location
|
|
171
|
-
req_types (list[LineRequestType], optional): List of types for
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
ValueError: Wrong location type provided e.g. LocationType.POI or LocationType.ADDRESS
|
|
469
|
+
location (str | Location): The location identifier or Location object.
|
|
470
|
+
req_types (list[LineRequestType], optional): List of request types for lines. Defaults to [].
|
|
471
|
+
merge_directions (bool, optional): Whether to merge directions. Defaults to False.
|
|
472
|
+
show_trains_explicit (bool, optional): Whether to explicitly show trains. Defaults to False.
|
|
175
473
|
|
|
176
474
|
Returns:
|
|
177
|
-
list[
|
|
475
|
+
list[Line]: A list of Line objects.
|
|
476
|
+
|
|
477
|
+
Raises:
|
|
478
|
+
ValueError: If the location is a Location object and its type is not STOP.
|
|
178
479
|
"""
|
|
179
480
|
_LOGGER.info("Request lines by location")
|
|
180
481
|
_LOGGER.debug(f"location:{location}")
|
|
181
|
-
_LOGGER.debug(f"
|
|
482
|
+
_LOGGER.debug(f"req_types :{req_types}")
|
|
483
|
+
|
|
484
|
+
if not location:
|
|
485
|
+
raise ValueError("No location provided")
|
|
182
486
|
|
|
183
487
|
if isinstance(location, Location):
|
|
184
488
|
if location.loc_type != LocationType.STOP:
|
|
@@ -187,22 +491,209 @@ class EfaClient:
|
|
|
187
491
|
)
|
|
188
492
|
location = location.id
|
|
189
493
|
|
|
190
|
-
command = CommandServingLines(
|
|
494
|
+
command = CommandServingLines(self._format)
|
|
495
|
+
command.add_param("mode", "odv")
|
|
496
|
+
command.add_param("locationServerActive", 1)
|
|
497
|
+
command.add_param("type_sl", "stopID")
|
|
498
|
+
command.add_param("name_sl", location)
|
|
499
|
+
command.add_param("mergeDir", merge_directions)
|
|
500
|
+
command.add_param("lsShowTrainsExplicit", show_trains_explicit)
|
|
501
|
+
command.add_param("coordOutputFormat", CoordFormat.WGS84.value)
|
|
191
502
|
|
|
192
503
|
if req_types:
|
|
193
504
|
command.add_param("lineReqType", sum(req_types))
|
|
194
505
|
|
|
506
|
+
command.validate_params()
|
|
507
|
+
|
|
508
|
+
response = await self._run_query(self._build_url(command))
|
|
509
|
+
|
|
510
|
+
return command.parse(response)
|
|
511
|
+
|
|
512
|
+
async def line_stops(
|
|
513
|
+
self, line_name: str, additional_info: bool = False
|
|
514
|
+
) -> list[Location]:
|
|
515
|
+
"""
|
|
516
|
+
Retrieve the stops for a given line.
|
|
517
|
+
|
|
518
|
+
Args:
|
|
519
|
+
line_name (str): The name of the line for which to retrieve stops.
|
|
520
|
+
additional_info (bool, optional): Whether to include additional stop information. Defaults to False.
|
|
521
|
+
|
|
522
|
+
Returns:
|
|
523
|
+
list[Location]: A list of Location objects representing the stops for the specified line.
|
|
524
|
+
"""
|
|
525
|
+
_LOGGER.info("Request lise stops")
|
|
526
|
+
_LOGGER.debug(f"line_name: {line_name}")
|
|
527
|
+
|
|
528
|
+
if not line_name:
|
|
529
|
+
raise ValueError("No line name provided")
|
|
530
|
+
|
|
531
|
+
command = CommandLineStop(self._format)
|
|
532
|
+
command.add_param("coordOutputFormat", CoordFormat.WGS84.value)
|
|
533
|
+
command.add_param("line", line_name)
|
|
534
|
+
command.add_param("allStopInfo", additional_info)
|
|
535
|
+
|
|
536
|
+
command.validate_params()
|
|
537
|
+
|
|
538
|
+
response = await self._run_query(self._build_url(command))
|
|
539
|
+
|
|
540
|
+
return command.parse(response)
|
|
541
|
+
|
|
542
|
+
async def coord_bounding_box(
|
|
543
|
+
self,
|
|
544
|
+
left_upper: tuple[float, float],
|
|
545
|
+
right_lower: tuple[float, float],
|
|
546
|
+
filters: list[PointTypeFilter],
|
|
547
|
+
limit: int = 10,
|
|
548
|
+
) -> list[Location]:
|
|
549
|
+
"""
|
|
550
|
+
Asynchronously request object coordinates within a bounding box.
|
|
551
|
+
|
|
552
|
+
Args:
|
|
553
|
+
left_upper (tuple[float, float]): The coordinates(WGS84 format) of the left upper corner of the bounding box (latitude, longitude).
|
|
554
|
+
right_lower (tuple[float, float]): The coordinates(WGS84 format) of the right lower corner of the bounding box (latitude, longitude).
|
|
555
|
+
filters (list[PointTypeFilter]): A list of filters to apply to the points within the bounding box.
|
|
556
|
+
limit (int, optional): The maximum number of locations to return. Defaults to 10.
|
|
557
|
+
|
|
558
|
+
Returns:
|
|
559
|
+
list[Location]: A list of Location objects that fall within the specified bounding box and match the given filters.
|
|
560
|
+
"""
|
|
561
|
+
_LOGGER.info("Request object(s) coordinates by bounding box")
|
|
562
|
+
_LOGGER.debug(f"left_upper: {left_upper}")
|
|
563
|
+
_LOGGER.debug(f"right_lower: {right_lower}")
|
|
564
|
+
_LOGGER.debug(f"filters: {filters}")
|
|
565
|
+
|
|
566
|
+
command = CommandCoord(self._format)
|
|
567
|
+
command.add_param("coordOutputFormat", CoordFormat.WGS84.value)
|
|
568
|
+
command.add_param("boundingBox", True)
|
|
569
|
+
command.add_param(
|
|
570
|
+
"boundingBoxLU",
|
|
571
|
+
f"{left_upper[0]}:{left_upper[1]}:{CoordFormat.WGS84.value}",
|
|
572
|
+
)
|
|
573
|
+
command.add_param(
|
|
574
|
+
"boundingBoxRL",
|
|
575
|
+
f"{right_lower[0]}:{right_lower[1]}:{CoordFormat.WGS84.value}",
|
|
576
|
+
)
|
|
577
|
+
command.add_param("inclFilter", True)
|
|
578
|
+
command.add_param("max", limit)
|
|
579
|
+
|
|
580
|
+
for index, f in enumerate(filters):
|
|
581
|
+
command.add_param(f"type_{index + 1}", f.value)
|
|
582
|
+
|
|
583
|
+
command.validate_params()
|
|
584
|
+
|
|
585
|
+
response = await self._run_query(self._build_url(command))
|
|
586
|
+
|
|
587
|
+
return command.parse(response)
|
|
588
|
+
|
|
589
|
+
async def coord_radial(
|
|
590
|
+
self,
|
|
591
|
+
coord: tuple[float, float],
|
|
592
|
+
filters: list[PointTypeFilter],
|
|
593
|
+
radius: list[int],
|
|
594
|
+
limit: int = 10,
|
|
595
|
+
) -> list[Location]:
|
|
596
|
+
"""
|
|
597
|
+
Asynchronously request object coordinates by radius.
|
|
598
|
+
|
|
599
|
+
Args:
|
|
600
|
+
coord (tuple[float, float]): A tuple containing the latitude and longitude of the coordinate(WGS84 format).
|
|
601
|
+
filters (list[PointTypeFilter]): A list of PointTypeFilter objects to filter the results.
|
|
602
|
+
radius (list[int]): A list of radii corresponding to each filter.
|
|
603
|
+
limit (int, optional): The maximum number of locations to return. Defaults to 10.
|
|
604
|
+
|
|
605
|
+
Returns:
|
|
606
|
+
list[Location]: A list of Location objects that match the given filters and radius.
|
|
607
|
+
|
|
608
|
+
Raises:
|
|
609
|
+
ValueError: If the length of radius and filters do not match.
|
|
610
|
+
"""
|
|
611
|
+
_LOGGER.info("Request object(s) coordinates by radius")
|
|
612
|
+
_LOGGER.debug(f"coord: {coord}")
|
|
613
|
+
_LOGGER.debug(f"filters: {filters}")
|
|
614
|
+
_LOGGER.debug(f"radius: {radius}")
|
|
615
|
+
|
|
616
|
+
if len(radius) != len(filters):
|
|
617
|
+
raise ValueError("Radius and filters must have the same length")
|
|
618
|
+
|
|
619
|
+
command = CommandCoord(self._format)
|
|
620
|
+
command.add_param("coordOutputFormat", CoordFormat.WGS84.value)
|
|
621
|
+
command.add_param("inclFilter", True)
|
|
622
|
+
command.add_param("coord", f"{coord[0]}:{coord[1]}:{CoordFormat.WGS84.value}")
|
|
623
|
+
command.add_param("max", limit)
|
|
624
|
+
|
|
625
|
+
for index, f in enumerate(filters):
|
|
626
|
+
command.add_param(f"type_{index + 1}", f.value)
|
|
627
|
+
command.add_param(f"radius_{index + 1}", radius[index])
|
|
628
|
+
|
|
629
|
+
command.validate_params()
|
|
630
|
+
|
|
195
631
|
response = await self._run_query(self._build_url(command))
|
|
196
632
|
|
|
197
633
|
return command.parse(response)
|
|
198
634
|
|
|
199
|
-
async def
|
|
200
|
-
|
|
635
|
+
async def geo_object(
|
|
636
|
+
self,
|
|
637
|
+
line: str,
|
|
638
|
+
filter_date: date | str | None = None,
|
|
639
|
+
left_upper: tuple[float, float] | None = None,
|
|
640
|
+
right_lower: tuple[float, float] | None = None,
|
|
641
|
+
) -> list[Line]:
|
|
642
|
+
"""
|
|
643
|
+
Asynchronously generate a sequence of coordinates and all passed stops of a provided line.
|
|
644
|
+
|
|
645
|
+
Args:
|
|
646
|
+
line (str): The line parameter to be used in the query.
|
|
647
|
+
filter_date (date | str | None, optional): The date to filter results by. Can be a date object or a string in the format 'YYYYMMDD'. Defaults to None.
|
|
648
|
+
left_upper (tuple[float, float] | None, optional): The left upper coordinate(WGS84 format) of the bounding box. Defaults to None.
|
|
649
|
+
right_lower (tuple[float, float] | None, optional): The right lower coordinate(WGS84 format) of the bounding box. Defaults to None.
|
|
650
|
+
|
|
651
|
+
Returns:
|
|
652
|
+
list[Line]: A list of Line objects that match the query parameters.
|
|
653
|
+
|
|
654
|
+
Raises:
|
|
655
|
+
ValueError: If the filter_date is not a valid date object or string in the format 'YYYYMMDD'.
|
|
656
|
+
"""
|
|
657
|
+
command = CommandGeoObject(self._format)
|
|
658
|
+
command.add_param("coordOutputFormat", CoordFormat.WGS84.value)
|
|
659
|
+
command.add_param("line", line)
|
|
660
|
+
|
|
661
|
+
if left_upper and right_lower:
|
|
662
|
+
command.add_param("boundingBox", True)
|
|
663
|
+
|
|
664
|
+
command.add_param(
|
|
665
|
+
"boundingBoxLU",
|
|
666
|
+
f"{left_upper[0]}:{left_upper[1]}:{CoordFormat.WGS84.value}",
|
|
667
|
+
)
|
|
668
|
+
command.add_param(
|
|
669
|
+
"boundingBoxRL",
|
|
670
|
+
f"{right_lower[0]}:{right_lower[1]}:{CoordFormat.WGS84.value}",
|
|
671
|
+
)
|
|
672
|
+
|
|
673
|
+
if filter_date:
|
|
674
|
+
if isinstance(filter_date, date):
|
|
675
|
+
filter_date = filter_date.strftime("%Y%m%d")
|
|
676
|
+
elif is_date(filter_date):
|
|
677
|
+
filter_date = filter_date
|
|
678
|
+
else:
|
|
679
|
+
raise ValueError(
|
|
680
|
+
"Invalid date format. Expected a date object or string in the format 'YYYYMMDD'"
|
|
681
|
+
)
|
|
682
|
+
|
|
683
|
+
command.add_param("filterDate", filter_date)
|
|
684
|
+
|
|
685
|
+
command.validate_params()
|
|
686
|
+
|
|
687
|
+
response = await self._run_query(self._build_url(command))
|
|
688
|
+
|
|
689
|
+
return command.parse(response)
|
|
201
690
|
|
|
202
691
|
async def _run_query(self, query: str) -> str:
|
|
203
692
|
_LOGGER.info(f"Run query {query}")
|
|
204
693
|
|
|
205
|
-
async with self._client_session.get(
|
|
694
|
+
async with self._client_session.get(
|
|
695
|
+
query, ssl=False, timeout=QUERY_TIMEOUT
|
|
696
|
+
) as response:
|
|
206
697
|
_LOGGER.debug(f"Response status: {response.status}")
|
|
207
698
|
|
|
208
699
|
if response.status == 200:
|