apyefa 0.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/__init__.py +21 -0
- apyefa/client.py +215 -0
- apyefa/commands/__init__.py +15 -0
- apyefa/commands/command.py +115 -0
- apyefa/commands/command_departures.py +49 -0
- apyefa/commands/command_serving_lines.py +60 -0
- apyefa/commands/command_stop_finder.py +48 -0
- apyefa/commands/command_system_info.py +28 -0
- apyefa/commands/command_trip.py +31 -0
- apyefa/commands/parsers/__init__.py +0 -0
- apyefa/commands/parsers/parser.py +7 -0
- apyefa/commands/parsers/rapid_json_parser.py +11 -0
- apyefa/commands/parsers/xml_parser.py +6 -0
- apyefa/data_classes.py +381 -0
- apyefa/exceptions.py +18 -0
- apyefa/helpers.py +74 -0
- apyefa-0.0.1.dist-info/LICENSE +21 -0
- apyefa-0.0.1.dist-info/METADATA +413 -0
- apyefa-0.0.1.dist-info/RECORD +21 -0
- apyefa-0.0.1.dist-info/WHEEL +5 -0
- apyefa-0.0.1.dist-info/top_level.txt +1 -0
apyefa/__init__.py
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
from apyefa.client import EfaClient
|
|
2
|
+
from apyefa.data_classes import (
|
|
3
|
+
Departure,
|
|
4
|
+
Line,
|
|
5
|
+
Location,
|
|
6
|
+
LocationFilter,
|
|
7
|
+
LocationType,
|
|
8
|
+
SystemInfo,
|
|
9
|
+
TransportType,
|
|
10
|
+
)
|
|
11
|
+
|
|
12
|
+
__all__ = [
|
|
13
|
+
"LocationFilter",
|
|
14
|
+
"Location",
|
|
15
|
+
"LocationType",
|
|
16
|
+
"Departure",
|
|
17
|
+
"SystemInfo",
|
|
18
|
+
"Line",
|
|
19
|
+
"TransportType",
|
|
20
|
+
"EfaClient",
|
|
21
|
+
]
|
apyefa/client.py
ADDED
|
@@ -0,0 +1,215 @@
|
|
|
1
|
+
import logging
|
|
2
|
+
|
|
3
|
+
import aiohttp
|
|
4
|
+
|
|
5
|
+
from apyefa.commands import (
|
|
6
|
+
Command,
|
|
7
|
+
CommandDepartures,
|
|
8
|
+
CommandServingLines,
|
|
9
|
+
CommandStopFinder,
|
|
10
|
+
CommandSystemInfo,
|
|
11
|
+
)
|
|
12
|
+
from apyefa.data_classes import (
|
|
13
|
+
CoordFormat,
|
|
14
|
+
Departure,
|
|
15
|
+
Line,
|
|
16
|
+
Location,
|
|
17
|
+
LocationFilter,
|
|
18
|
+
LocationType,
|
|
19
|
+
SystemInfo,
|
|
20
|
+
)
|
|
21
|
+
from apyefa.exceptions import EfaConnectionError
|
|
22
|
+
|
|
23
|
+
_LOGGER = logging.getLogger(__name__)
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
class EfaClient:
|
|
27
|
+
async def __aenter__(self):
|
|
28
|
+
self._client_session = aiohttp.ClientSession()
|
|
29
|
+
return self
|
|
30
|
+
|
|
31
|
+
async def __aexit__(self, *args, **kwargs):
|
|
32
|
+
await self._client_session.__aexit__(*args, **kwargs)
|
|
33
|
+
|
|
34
|
+
def __init__(self, url: str, debug: bool = False):
|
|
35
|
+
"""Create a new instance of client.
|
|
36
|
+
|
|
37
|
+
Args:
|
|
38
|
+
url (str): url string to EFA endpoint
|
|
39
|
+
|
|
40
|
+
Raises:
|
|
41
|
+
ValueError: No url provided
|
|
42
|
+
"""
|
|
43
|
+
if not url:
|
|
44
|
+
raise ValueError("No EFA endpoint url provided")
|
|
45
|
+
|
|
46
|
+
self._debug: bool = debug
|
|
47
|
+
self._base_url: str = url if url.endswith("/") else f"{url}/"
|
|
48
|
+
|
|
49
|
+
async def info(self) -> SystemInfo:
|
|
50
|
+
"""Get system info used by EFA endpoint.
|
|
51
|
+
|
|
52
|
+
Returns:
|
|
53
|
+
SystemInfo: info object
|
|
54
|
+
"""
|
|
55
|
+
_LOGGER.info("Request system info")
|
|
56
|
+
|
|
57
|
+
command = CommandSystemInfo()
|
|
58
|
+
response = await self._run_query(self._build_url(command))
|
|
59
|
+
|
|
60
|
+
return command.parse(response)
|
|
61
|
+
|
|
62
|
+
async def locations_by_name(
|
|
63
|
+
self, name: str, *, filters: list[LocationFilter] = [], limit: int = 30
|
|
64
|
+
) -> list[Location]:
|
|
65
|
+
"""Find location(s) by provided `name`.
|
|
66
|
+
|
|
67
|
+
Args:
|
|
68
|
+
name (str): Name or ID of location to search (case insensitive)
|
|
69
|
+
e.g. "Plärrer", "Nordostbanhof" or "de:09564:704"
|
|
70
|
+
filters (list[LocationFilter], optional): List of filters to apply for search. Defaults to empty.
|
|
71
|
+
limit (int, optional): Max size of returned list. Defaults to 30.
|
|
72
|
+
|
|
73
|
+
Returns:
|
|
74
|
+
list[Location]: List of location(s) returned by endpoint. List is sorted by match quality.
|
|
75
|
+
"""
|
|
76
|
+
_LOGGER.info(f"Request location search by name/id: {name}")
|
|
77
|
+
_LOGGER.debug(f"filters: {filters}")
|
|
78
|
+
_LOGGER.debug(f"limit: {limit}")
|
|
79
|
+
|
|
80
|
+
command = CommandStopFinder("any", name)
|
|
81
|
+
command.add_param("anyMaxSizeHitList", limit)
|
|
82
|
+
|
|
83
|
+
if filters:
|
|
84
|
+
command.add_param("anyObjFilter_sf", sum(filters))
|
|
85
|
+
|
|
86
|
+
response = await self._run_query(self._build_url(command))
|
|
87
|
+
|
|
88
|
+
return command.parse(response)
|
|
89
|
+
|
|
90
|
+
async def location_by_coord(
|
|
91
|
+
self,
|
|
92
|
+
coord_x: float,
|
|
93
|
+
coord_y: float,
|
|
94
|
+
format: CoordFormat = CoordFormat.WGS84,
|
|
95
|
+
limit: int = 10,
|
|
96
|
+
) -> Location:
|
|
97
|
+
"""Find location(s) by provided `coordinates`.
|
|
98
|
+
|
|
99
|
+
Args:
|
|
100
|
+
coord_x (float): X coordinate
|
|
101
|
+
coord_y (float): Y coordinate
|
|
102
|
+
format (CoordFormat, optional): Coordinate format. Defaults to CoordFormat.WGS84.
|
|
103
|
+
limit (int, optional): Max size of returned list. Defaults to 10.
|
|
104
|
+
|
|
105
|
+
Returns:
|
|
106
|
+
Location: List of location(s) returned by endpoint. List is sorted by match quality.
|
|
107
|
+
"""
|
|
108
|
+
_LOGGER.info("Request location search by coordinates")
|
|
109
|
+
_LOGGER.debug(f"coord_x: {coord_x}")
|
|
110
|
+
_LOGGER.debug(f"coord_y: {coord_y}")
|
|
111
|
+
_LOGGER.debug(f"format: {format}")
|
|
112
|
+
_LOGGER.debug(f"limit: {limit}")
|
|
113
|
+
|
|
114
|
+
command = CommandStopFinder("coord", f"{coord_x}:{coord_y}:{format}")
|
|
115
|
+
command.add_param("anyMaxSizeHitList", limit)
|
|
116
|
+
|
|
117
|
+
response = await self._run_query(self._build_url(command))
|
|
118
|
+
|
|
119
|
+
return command.parse(response)
|
|
120
|
+
|
|
121
|
+
async def trip(self):
|
|
122
|
+
raise NotImplementedError
|
|
123
|
+
|
|
124
|
+
async def departures_by_location(
|
|
125
|
+
self,
|
|
126
|
+
stop: Location | str,
|
|
127
|
+
limit=40,
|
|
128
|
+
date: str | None = None,
|
|
129
|
+
) -> list[Departure]:
|
|
130
|
+
_LOGGER.info(f"Request departures for stop {stop}")
|
|
131
|
+
_LOGGER.debug(f"limit: {limit}")
|
|
132
|
+
_LOGGER.debug(f"date: {date}")
|
|
133
|
+
|
|
134
|
+
if isinstance(stop, Location):
|
|
135
|
+
stop = stop.id
|
|
136
|
+
|
|
137
|
+
command = CommandDepartures(stop)
|
|
138
|
+
|
|
139
|
+
# add parameters
|
|
140
|
+
command.add_param("limit", limit)
|
|
141
|
+
command.add_param_datetime(date)
|
|
142
|
+
|
|
143
|
+
response = await self._run_query(self._build_url(command))
|
|
144
|
+
|
|
145
|
+
return command.parse(response)
|
|
146
|
+
|
|
147
|
+
async def lines_by_name(self, line: str) -> list[Line]:
|
|
148
|
+
"""Search lines by name. e.g. subway `U3` or bus `65`
|
|
149
|
+
|
|
150
|
+
Args:
|
|
151
|
+
line (str): Line name to search
|
|
152
|
+
|
|
153
|
+
Returns:
|
|
154
|
+
list[Transport]: List of lines
|
|
155
|
+
"""
|
|
156
|
+
_LOGGER.info("Request lines by name")
|
|
157
|
+
_LOGGER.debug(f"line:{line}")
|
|
158
|
+
|
|
159
|
+
command = CommandServingLines("line", line)
|
|
160
|
+
|
|
161
|
+
response = await self._run_query(self._build_url(command))
|
|
162
|
+
|
|
163
|
+
return command.parse(response)
|
|
164
|
+
|
|
165
|
+
async def lines_by_location(self, location: str | Location) -> list[Line]:
|
|
166
|
+
"""Search for lines that pass `location`. Location can be location ID like `de:08111:6221` or a Location object
|
|
167
|
+
|
|
168
|
+
Args:
|
|
169
|
+
location (str | Location): Location
|
|
170
|
+
|
|
171
|
+
Raises:
|
|
172
|
+
ValueError: If not a stop location provided but e.g. POI or Address
|
|
173
|
+
|
|
174
|
+
Returns:
|
|
175
|
+
list[Transport]: List of lines
|
|
176
|
+
"""
|
|
177
|
+
_LOGGER.info("Request lines by location")
|
|
178
|
+
_LOGGER.debug(f"location:{location}")
|
|
179
|
+
|
|
180
|
+
if isinstance(location, Location):
|
|
181
|
+
if location.loc_type != LocationType.STOP:
|
|
182
|
+
raise ValueError(
|
|
183
|
+
f"Only locations with type Stop are supported, provided {location.loc_type}"
|
|
184
|
+
)
|
|
185
|
+
location = location.id
|
|
186
|
+
|
|
187
|
+
command = CommandServingLines("odv", location)
|
|
188
|
+
|
|
189
|
+
response = await self._run_query(self._build_url(command))
|
|
190
|
+
|
|
191
|
+
return command.parse(response)
|
|
192
|
+
|
|
193
|
+
async def locations_by_line(self, line: str | Line) -> list[Location]:
|
|
194
|
+
raise NotImplementedError
|
|
195
|
+
|
|
196
|
+
async def _run_query(self, query: str) -> str:
|
|
197
|
+
_LOGGER.info(f"Run query {query}")
|
|
198
|
+
|
|
199
|
+
async with self._client_session.get(query, ssl=False) as response:
|
|
200
|
+
_LOGGER.debug(f"Response status: {response.status}")
|
|
201
|
+
|
|
202
|
+
if response.status == 200:
|
|
203
|
+
text = await response.text()
|
|
204
|
+
|
|
205
|
+
if self._debug:
|
|
206
|
+
_LOGGER.debug(text)
|
|
207
|
+
|
|
208
|
+
return text
|
|
209
|
+
else:
|
|
210
|
+
raise EfaConnectionError(
|
|
211
|
+
f"Failed to fetch data from endpoint. Returned status: {response.status}"
|
|
212
|
+
)
|
|
213
|
+
|
|
214
|
+
def _build_url(self, cmd: Command):
|
|
215
|
+
return self._base_url + str(cmd)
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
from .command import Command
|
|
2
|
+
from .command_departures import CommandDepartures
|
|
3
|
+
from .command_serving_lines import CommandServingLines
|
|
4
|
+
from .command_stop_finder import CommandStopFinder
|
|
5
|
+
from .command_system_info import CommandSystemInfo
|
|
6
|
+
from .command_trip import CommandTrip
|
|
7
|
+
|
|
8
|
+
__all__ = [
|
|
9
|
+
"Command",
|
|
10
|
+
"CommandDepartures",
|
|
11
|
+
"CommandStopFinder",
|
|
12
|
+
"CommandSystemInfo",
|
|
13
|
+
"CommandTrip",
|
|
14
|
+
"CommandServingLines",
|
|
15
|
+
]
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
import logging
|
|
2
|
+
from abc import abstractmethod
|
|
3
|
+
|
|
4
|
+
from voluptuous import MultipleInvalid, Schema
|
|
5
|
+
|
|
6
|
+
from apyefa.commands.parsers.rapid_json_parser import RapidJsonParser
|
|
7
|
+
from apyefa.exceptions import EfaFormatNotSupported, EfaParameterError
|
|
8
|
+
from apyefa.helpers import is_date, is_datetime, is_time
|
|
9
|
+
|
|
10
|
+
_LOGGER = logging.getLogger(__name__)
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class Command:
|
|
14
|
+
def __init__(self, name: str, macro: str, output_format: str = "rapidJSON") -> None:
|
|
15
|
+
self._name: str = name
|
|
16
|
+
self._macro: str = macro
|
|
17
|
+
self._parameters: dict[str, str] = {}
|
|
18
|
+
self._format: str = output_format
|
|
19
|
+
|
|
20
|
+
self.add_param("outputFormat", output_format)
|
|
21
|
+
self.add_param("coordOutputFormat", "WGS84")
|
|
22
|
+
|
|
23
|
+
def add_param(self, param: str, value: str):
|
|
24
|
+
if not param or not value:
|
|
25
|
+
return
|
|
26
|
+
|
|
27
|
+
if param not in self._get_params_schema().schema.keys():
|
|
28
|
+
raise EfaParameterError(
|
|
29
|
+
f"Parameter {param} is now allowed for this command"
|
|
30
|
+
)
|
|
31
|
+
|
|
32
|
+
_LOGGER.debug(f'Add parameter "{param}" with value "{value}"')
|
|
33
|
+
|
|
34
|
+
self._parameters.update({param: value})
|
|
35
|
+
|
|
36
|
+
_LOGGER.debug("Updated parameters:")
|
|
37
|
+
_LOGGER.debug(self._parameters)
|
|
38
|
+
|
|
39
|
+
def add_param_datetime(self, date: str):
|
|
40
|
+
if not date:
|
|
41
|
+
return
|
|
42
|
+
|
|
43
|
+
if is_datetime(date):
|
|
44
|
+
self.add_param("itdDate", date.split(" ")[0])
|
|
45
|
+
self.add_param("itdTime", date.split(" ")[1].replace(":", ""))
|
|
46
|
+
elif is_date(date):
|
|
47
|
+
self.add_param("itdDate", date)
|
|
48
|
+
elif is_time(date):
|
|
49
|
+
self.add_param("itdTime", date.replace(":", ""))
|
|
50
|
+
else:
|
|
51
|
+
raise ValueError("Date(time) provided in invalid format")
|
|
52
|
+
|
|
53
|
+
def to_str(self) -> str:
|
|
54
|
+
self._parameters = self.extend_with_defaults()
|
|
55
|
+
self.validate()
|
|
56
|
+
|
|
57
|
+
return f"{self._name}?commonMacro={self._macro}" + self._get_params_as_str()
|
|
58
|
+
|
|
59
|
+
def __str__(self) -> str:
|
|
60
|
+
return self.to_str()
|
|
61
|
+
|
|
62
|
+
def validate(self):
|
|
63
|
+
"""Validate self._parameters
|
|
64
|
+
|
|
65
|
+
Raises:
|
|
66
|
+
EfaParameterError: some of parameters are missing or have invalid values
|
|
67
|
+
"""
|
|
68
|
+
params_schema = self._get_params_schema()
|
|
69
|
+
|
|
70
|
+
try:
|
|
71
|
+
params = self.extend_with_defaults()
|
|
72
|
+
params_schema(params)
|
|
73
|
+
except MultipleInvalid as exc:
|
|
74
|
+
_LOGGER.error("Parameters validation failed", exc_info=exc)
|
|
75
|
+
raise EfaParameterError(str(exc)) from exc
|
|
76
|
+
|
|
77
|
+
def extend_with_defaults(self) -> dict:
|
|
78
|
+
"""Extend self._parameters with default values
|
|
79
|
+
|
|
80
|
+
Returns:
|
|
81
|
+
dict: parameters extended with default values
|
|
82
|
+
"""
|
|
83
|
+
|
|
84
|
+
params_schema = self._get_params_schema()
|
|
85
|
+
|
|
86
|
+
return params_schema(self._parameters)
|
|
87
|
+
|
|
88
|
+
def _get_params_as_str(self) -> str:
|
|
89
|
+
"""Return parameters concatenated with &
|
|
90
|
+
|
|
91
|
+
Returns:
|
|
92
|
+
str: parameters as string
|
|
93
|
+
"""
|
|
94
|
+
if not self._parameters:
|
|
95
|
+
return ""
|
|
96
|
+
|
|
97
|
+
return "&" + "&".join([f"{k}={str(v)}" for k, v in self._parameters.items()])
|
|
98
|
+
|
|
99
|
+
@abstractmethod
|
|
100
|
+
def parse(self, data: str):
|
|
101
|
+
raise NotImplementedError("Abstract method not implemented")
|
|
102
|
+
|
|
103
|
+
@abstractmethod
|
|
104
|
+
def _get_params_schema(self) -> Schema:
|
|
105
|
+
raise NotImplementedError("Abstract method not implemented")
|
|
106
|
+
|
|
107
|
+
@abstractmethod
|
|
108
|
+
def _get_parser(self):
|
|
109
|
+
match self._format:
|
|
110
|
+
case "rapidJSON":
|
|
111
|
+
return RapidJsonParser()
|
|
112
|
+
case _:
|
|
113
|
+
raise EfaFormatNotSupported(
|
|
114
|
+
f"Output format {self._format} is not supported"
|
|
115
|
+
)
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import logging
|
|
2
|
+
|
|
3
|
+
from voluptuous import Any, Date, Datetime, Optional, Required, Schema
|
|
4
|
+
|
|
5
|
+
from apyefa.commands.command import Command
|
|
6
|
+
from apyefa.data_classes import Departure
|
|
7
|
+
|
|
8
|
+
_LOGGER = logging.getLogger(__name__)
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class CommandDepartures(Command):
|
|
12
|
+
def __init__(self, stop: str) -> None:
|
|
13
|
+
super().__init__("XML_DM_REQUEST", "dm")
|
|
14
|
+
|
|
15
|
+
self.add_param("name_dm", stop)
|
|
16
|
+
|
|
17
|
+
def parse(self, data: dict):
|
|
18
|
+
data = self._get_parser().parse(data)
|
|
19
|
+
|
|
20
|
+
departures = data.get("stopEvents", [])
|
|
21
|
+
|
|
22
|
+
_LOGGER.info(f"{len(departures)} departure(s) found")
|
|
23
|
+
|
|
24
|
+
result = []
|
|
25
|
+
|
|
26
|
+
for departure in departures:
|
|
27
|
+
result.append(Departure.from_dict(departure))
|
|
28
|
+
|
|
29
|
+
return result
|
|
30
|
+
|
|
31
|
+
def _get_params_schema(self) -> Schema:
|
|
32
|
+
return Schema(
|
|
33
|
+
{
|
|
34
|
+
Required("outputFormat", default="rapidJSON"): Any("rapidJSON"),
|
|
35
|
+
Required("coordOutputFormat", default="WGS84"): Any("WGS84"),
|
|
36
|
+
Required("name_dm"): str,
|
|
37
|
+
Required("type_dm", default="stop"): Any("any", "stop"),
|
|
38
|
+
Required("mode", default="direct"): Any("any", "direct"),
|
|
39
|
+
Optional("itdTime"): Datetime("%M%S"),
|
|
40
|
+
Optional("itdDate"): Date("%Y%m%d"),
|
|
41
|
+
Optional("useAllStops"): Any("0", "1", 0, 1),
|
|
42
|
+
Optional("useRealtime", default=1): Any("0", "1", 0, 1),
|
|
43
|
+
Optional("lsShowTrainsExplicit"): Any("0", "1", 0, 1),
|
|
44
|
+
Optional("useProxFootSearch"): Any("0", "1", 0, 1),
|
|
45
|
+
Optional("deleteAssigendStops_dm"): Any("0", "1", 0, 1),
|
|
46
|
+
Optional("doNotSearchForStops_dm"): Any("0", "1", 0, 1),
|
|
47
|
+
Optional("limit"): int,
|
|
48
|
+
}
|
|
49
|
+
)
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import logging
|
|
2
|
+
|
|
3
|
+
from voluptuous import Any, Optional, Required, Schema
|
|
4
|
+
|
|
5
|
+
from apyefa.commands.command import Command
|
|
6
|
+
from apyefa.data_classes import Line
|
|
7
|
+
|
|
8
|
+
_LOGGER = logging.getLogger(__name__)
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class CommandServingLines(Command):
|
|
12
|
+
def __init__(self, mode: str, value: str) -> None:
|
|
13
|
+
super().__init__("XML_SERVINGLINES_REQUEST", "servingLines")
|
|
14
|
+
|
|
15
|
+
match mode:
|
|
16
|
+
case "odv":
|
|
17
|
+
self.add_param("type_sl", "stopID")
|
|
18
|
+
self.add_param("name_sl", value)
|
|
19
|
+
case "line":
|
|
20
|
+
self.add_param("lineName", value)
|
|
21
|
+
case _:
|
|
22
|
+
raise ValueError(f"Mode {mode} not supported for serving lines")
|
|
23
|
+
|
|
24
|
+
self.add_param("mode", mode)
|
|
25
|
+
|
|
26
|
+
def parse(self, data: dict) -> list[Line]:
|
|
27
|
+
data = self._get_parser().parse(data)
|
|
28
|
+
|
|
29
|
+
transportations = data.get("lines", [])
|
|
30
|
+
|
|
31
|
+
_LOGGER.info(f"{len(transportations)} transportation(s) found")
|
|
32
|
+
|
|
33
|
+
result = []
|
|
34
|
+
|
|
35
|
+
for t in transportations:
|
|
36
|
+
result.append(Line.from_dict(t))
|
|
37
|
+
|
|
38
|
+
return result
|
|
39
|
+
|
|
40
|
+
def _get_params_schema(self) -> Schema:
|
|
41
|
+
return Schema(
|
|
42
|
+
{
|
|
43
|
+
Required("outputFormat", default="rapidJSON"): Any("rapidJSON"),
|
|
44
|
+
Required("coordOutputFormat", default="WGS84"): Any("WGS84"),
|
|
45
|
+
Required("mode", default="line"): Any("odv", "line"),
|
|
46
|
+
# mode 'odv'
|
|
47
|
+
Optional("type_sl"): Any("stopID"),
|
|
48
|
+
Optional("name_sl"): str,
|
|
49
|
+
# mode 'line'
|
|
50
|
+
Optional("lineName"): str,
|
|
51
|
+
Optional("lineReqType"): int,
|
|
52
|
+
Optional("mergeDir"): Any("0", "1", 0, 1),
|
|
53
|
+
Optional("lsShowTrainsExplicit"): Any("0", "1", 0, 1),
|
|
54
|
+
Optional("line"): str,
|
|
55
|
+
# Optional("doNotSearchForStops_sf"): Any("0", "1", 0, 1),
|
|
56
|
+
# Optional("anyObjFilter_origin"): Range(
|
|
57
|
+
# min=0, max=sum([x.value for x in StopFilter])
|
|
58
|
+
# ),
|
|
59
|
+
}
|
|
60
|
+
)
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import logging
|
|
2
|
+
|
|
3
|
+
from voluptuous import Any, Optional, Range, Required, Schema
|
|
4
|
+
|
|
5
|
+
from apyefa.commands.command import Command
|
|
6
|
+
from apyefa.data_classes import Location, LocationFilter
|
|
7
|
+
|
|
8
|
+
_LOGGER = logging.getLogger(__name__)
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class CommandStopFinder(Command):
|
|
12
|
+
def __init__(self, req_type: str, name: str) -> None:
|
|
13
|
+
super().__init__("XML_STOPFINDER_REQUEST", "stopfinder")
|
|
14
|
+
|
|
15
|
+
self.add_param("type_sf", req_type)
|
|
16
|
+
self.add_param("name_sf", name)
|
|
17
|
+
|
|
18
|
+
def parse(self, data: dict) -> list[Location]:
|
|
19
|
+
data = self._get_parser().parse(data)
|
|
20
|
+
|
|
21
|
+
locations = data.get("locations", [])
|
|
22
|
+
|
|
23
|
+
_LOGGER.info(f"{len(locations)} location(s) found")
|
|
24
|
+
|
|
25
|
+
result = []
|
|
26
|
+
|
|
27
|
+
for location in locations:
|
|
28
|
+
result.append(Location.from_dict(location))
|
|
29
|
+
|
|
30
|
+
return sorted(result, key=lambda x: x.match_quality, reverse=True)
|
|
31
|
+
|
|
32
|
+
def _get_params_schema(self) -> Schema:
|
|
33
|
+
return Schema(
|
|
34
|
+
{
|
|
35
|
+
Required("outputFormat", default="rapidJSON"): Any("rapidJSON"),
|
|
36
|
+
Required("coordOutputFormat", default="WGS84"): Any("WGS84"),
|
|
37
|
+
Required("type_sf", default="any"): Any("any", "coord"),
|
|
38
|
+
Required("name_sf"): str,
|
|
39
|
+
Optional("anyMaxSizeHitList"): int,
|
|
40
|
+
Optional("anySigWhenPerfectNoOtherMatches"): Any("0", "1", 0, 1),
|
|
41
|
+
Optional("anyResSort_sf"): str,
|
|
42
|
+
Optional("anyObjFilter_sf"): int,
|
|
43
|
+
Optional("doNotSearchForStops_sf"): Any("0", "1", 0, 1),
|
|
44
|
+
Optional("anyObjFilter_origin"): Range(
|
|
45
|
+
min=0, max=sum([x.value for x in LocationFilter])
|
|
46
|
+
),
|
|
47
|
+
}
|
|
48
|
+
)
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import logging
|
|
2
|
+
|
|
3
|
+
from voluptuous import Any, Optional, Required, Schema
|
|
4
|
+
|
|
5
|
+
from apyefa.commands.command import Command
|
|
6
|
+
from apyefa.data_classes import SystemInfo
|
|
7
|
+
|
|
8
|
+
_LOGGER = logging.getLogger(__name__)
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class CommandSystemInfo(Command):
|
|
12
|
+
def __init__(self) -> None:
|
|
13
|
+
super().__init__("XML_SYSTEMINFO_REQUEST", "system")
|
|
14
|
+
|
|
15
|
+
def parse(self, data: dict) -> SystemInfo:
|
|
16
|
+
_LOGGER.info("Parsing system info response")
|
|
17
|
+
|
|
18
|
+
data = self._get_parser().parse(data)
|
|
19
|
+
|
|
20
|
+
return SystemInfo.from_dict(data)
|
|
21
|
+
|
|
22
|
+
def _get_params_schema(self) -> Schema:
|
|
23
|
+
return Schema(
|
|
24
|
+
{
|
|
25
|
+
Required("outputFormat", default="rapidJSON"): Any("rapidJSON"),
|
|
26
|
+
Optional("coordOutputFormat", default="WGS84"): Any("WGS84"),
|
|
27
|
+
}
|
|
28
|
+
)
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import logging
|
|
2
|
+
|
|
3
|
+
from voluptuous import Any, Optional, Required, Schema
|
|
4
|
+
|
|
5
|
+
from apyefa.commands.command import Command
|
|
6
|
+
|
|
7
|
+
_LOGGER = logging.getLogger(__name__)
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
class CommandTrip(Command):
|
|
11
|
+
def __init__(self) -> None:
|
|
12
|
+
super().__init__("XML_TRIP_REQUEST2", "trip")
|
|
13
|
+
|
|
14
|
+
def parse(self, data: dict):
|
|
15
|
+
raise NotImplementedError
|
|
16
|
+
|
|
17
|
+
def _get_params_schema(self) -> Schema:
|
|
18
|
+
return Schema(
|
|
19
|
+
{
|
|
20
|
+
Required("outputFormat", default="rapidJSON"): Any("rapidJSON"),
|
|
21
|
+
Required("coordOutputFormat", default="WGS84"): Any("WGS84"),
|
|
22
|
+
Required("type_origin", default="any"): Any("any", "coord"),
|
|
23
|
+
Required("name_origin"): str,
|
|
24
|
+
Required("type_destination", default="any"): Any("any", "coord"),
|
|
25
|
+
Required("name_destination"): str,
|
|
26
|
+
Optional("type_via", default="any"): Any("any", "coord"),
|
|
27
|
+
Optional("name_via"): str,
|
|
28
|
+
Optional("useUT"): Any("0", "1", 0, 1),
|
|
29
|
+
Optional("useRealtime"): Any("0", "1", 0, 1),
|
|
30
|
+
}
|
|
31
|
+
)
|
|
File without changes
|