PyTransportNSWv2 0.5.6__tar.gz → 0.6.5__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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: PyTransportNSWv2
3
- Version: 0.5.6
3
+ Version: 0.6.5
4
4
  Summary: Get detailed per-trip transport information from TransportNSW
5
5
  Home-page: https://github.com/andystewart999/TransportNSW
6
6
  Author: andystewart999
@@ -15,7 +15,7 @@ Description: # TransportNSWv2
15
15
  https://opendata.transport.nsw.gov.au/user-guide. You need to register an application that needs both the Trip Planner and Realtime Vehicle Positions APIs
16
16
 
17
17
  ### Get the stop IDs
18
- The function needs the stop IDs for the source and destination, and optionally how many minutes from now the departure should be, and if you want to filter trips by a specific transport type. The easiest way to get the stop ID is via https://transportnsw.info/stops#/. It provides the option to search for either a location or a specific platform, bus stop or ferry wharf. Regardless of if you specify a general location for the origin or destination, the return information shows the stop_id for the actual arrival and destination platform, bus stop or ferry wharf.
18
+ The function needs the stop IDs for the source and destination, and optionally how many minutes from now the departure should be, and if you want to filter trips by a specific transport type, or to only include trips that have specific text somewhere in the line/service details (see below). The easiest way to get the stop ID is via https://transportnsw.info/stops#/. It provides the option to search for either a location or a specific platform, bus stop or ferry wharf. Regardless of if you specify a general location for the origin or destination, the return information shows the stop_id for the actual arrival and destination platform, bus stop or ferry wharf.
19
19
 
20
20
  If it's available, the general occupancy level and the latitude and longitude of the selected journey's vehicle (train, bus, etc) will be returned.
21
21
 
@@ -24,7 +24,21 @@ Description: # TransportNSWv2
24
24
 
25
25
  ### Parameters
26
26
  ```python
27
- .get_trip(origin_stop_id, destination_stop_id, api_key, [trip_wait_time = 0], [transport_type = 0])
27
+ .get_trip(origin_stop_id, destination_stop_id, api_key, [trip_wait_time = 0], [transport_type = 0], [strict_transport_type = True|False], [raw_output = True|False], [journeys_to_return = 1], [route_filter = ''] )
28
+ ```
29
+
30
+ Transport types:
31
+ ```
32
+ 1: Train
33
+ 2: Metro
34
+ 4: Light rail
35
+ 5: Bus
36
+ 7: Coach
37
+ 9: Ferry
38
+ 11: School bus
39
+ 99: Walk
40
+ 100: Walk
41
+ 107: Cycle
28
42
  ```
29
43
 
30
44
  TransportNSW's trip planner can work better if you use the general location IDs (eg Central Station) rather than a specific Stop ID (eg Central Station, Platform 19) for the destination, depending on the transport type. Forcing a specific end destination sometimes results in much more complicated trips. Also note that the API expects (and returns) the Stop IDs as strings, although so far they all appear to be numeric.
@@ -44,6 +58,9 @@ Description: # TransportNSWv2
44
58
  ```python
45
59
  {"due": 3, "origin_stop_id": "207537", "origin_name": "Mona Vale Rd at Shinfield Ave, St Ives", "departure_time": "2024-05-20T21:59:48Z", "destination_stop_id": "2000338", "destination_name": "Central Station, Platform 18, Sydney", "arrival_time": "2024-05-20T22:47:36Z", "origin_transport_type": "Bus", "origin_transport_name": "Sydney Buses Network", "origin_line_name": "195", "origin_line_name_short": "195", "changes": 1, "occupancy": "MANY_SEATS", "real_time_trip_id": "2096551", "latitude": -33.72665786743164, "longitude": 151.16305541992188}
46
60
  ```
61
+
62
+ ```origin_line_name``` and ```origin_line_name_short``` are the fields that have the route filter applied, if present. For buses they are usually the same, but for trains and ferries they generally show the full and short line names. Both fields are checked and if either meet the filter then the journey is returned.
63
+
47
64
  Fun fact: TransportNSW's raw API output calls itself JSON, but it uses single quotes for strings in defiance of the JSON standards. When using this wrapper the output is formatted such that `jq`, for example, is happy with it.
48
65
 
49
66
  * due: the time (in minutes) before the journey starts
@@ -62,7 +79,8 @@ Description: # TransportNSWv2
62
79
  * latitude & longitude: The location of the vehicle, if available
63
80
 
64
81
  Please note that the origin and destination detail is just that - information about the first and last stops on the journey at the time the request was made. We don't return any intermediate steps, transport change types etc other than the total number of changes - the assumption is that you'll know the details of your specified trip, you just want to know when the next departure is. If you need much more detailed information then I recommend that you use the full Transport NSW trip planner website or application.
65
- Also note that the 'transport_type' filter, if present, only makes sure that at least one leg of the journey includes that transport type.
82
+
83
+ Also note that the 'transport_type' filter, if present, only makes sure that at least one leg of the journey includes that transport type unless 'strict_transport_type' is True, in which case the first leg MUST be of the requested type to be returned.
66
84
 
67
85
  ## Thank you
68
86
  Thank you Dav0815 for your TransportNSW library that the vast majority of this fork is based on. I couldn't have done it without you!
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: PyTransportNSWv2
3
- Version: 0.5.6
3
+ Version: 0.6.5
4
4
  Summary: Get detailed per-trip transport information from TransportNSW
5
5
  Home-page: https://github.com/andystewart999/TransportNSW
6
6
  Author: andystewart999
@@ -15,7 +15,7 @@ Description: # TransportNSWv2
15
15
  https://opendata.transport.nsw.gov.au/user-guide. You need to register an application that needs both the Trip Planner and Realtime Vehicle Positions APIs
16
16
 
17
17
  ### Get the stop IDs
18
- The function needs the stop IDs for the source and destination, and optionally how many minutes from now the departure should be, and if you want to filter trips by a specific transport type. The easiest way to get the stop ID is via https://transportnsw.info/stops#/. It provides the option to search for either a location or a specific platform, bus stop or ferry wharf. Regardless of if you specify a general location for the origin or destination, the return information shows the stop_id for the actual arrival and destination platform, bus stop or ferry wharf.
18
+ The function needs the stop IDs for the source and destination, and optionally how many minutes from now the departure should be, and if you want to filter trips by a specific transport type, or to only include trips that have specific text somewhere in the line/service details (see below). The easiest way to get the stop ID is via https://transportnsw.info/stops#/. It provides the option to search for either a location or a specific platform, bus stop or ferry wharf. Regardless of if you specify a general location for the origin or destination, the return information shows the stop_id for the actual arrival and destination platform, bus stop or ferry wharf.
19
19
 
20
20
  If it's available, the general occupancy level and the latitude and longitude of the selected journey's vehicle (train, bus, etc) will be returned.
21
21
 
@@ -24,7 +24,21 @@ Description: # TransportNSWv2
24
24
 
25
25
  ### Parameters
26
26
  ```python
27
- .get_trip(origin_stop_id, destination_stop_id, api_key, [trip_wait_time = 0], [transport_type = 0])
27
+ .get_trip(origin_stop_id, destination_stop_id, api_key, [trip_wait_time = 0], [transport_type = 0], [strict_transport_type = True|False], [raw_output = True|False], [journeys_to_return = 1], [route_filter = ''] )
28
+ ```
29
+
30
+ Transport types:
31
+ ```
32
+ 1: Train
33
+ 2: Metro
34
+ 4: Light rail
35
+ 5: Bus
36
+ 7: Coach
37
+ 9: Ferry
38
+ 11: School bus
39
+ 99: Walk
40
+ 100: Walk
41
+ 107: Cycle
28
42
  ```
29
43
 
30
44
  TransportNSW's trip planner can work better if you use the general location IDs (eg Central Station) rather than a specific Stop ID (eg Central Station, Platform 19) for the destination, depending on the transport type. Forcing a specific end destination sometimes results in much more complicated trips. Also note that the API expects (and returns) the Stop IDs as strings, although so far they all appear to be numeric.
@@ -44,6 +58,9 @@ Description: # TransportNSWv2
44
58
  ```python
45
59
  {"due": 3, "origin_stop_id": "207537", "origin_name": "Mona Vale Rd at Shinfield Ave, St Ives", "departure_time": "2024-05-20T21:59:48Z", "destination_stop_id": "2000338", "destination_name": "Central Station, Platform 18, Sydney", "arrival_time": "2024-05-20T22:47:36Z", "origin_transport_type": "Bus", "origin_transport_name": "Sydney Buses Network", "origin_line_name": "195", "origin_line_name_short": "195", "changes": 1, "occupancy": "MANY_SEATS", "real_time_trip_id": "2096551", "latitude": -33.72665786743164, "longitude": 151.16305541992188}
46
60
  ```
61
+
62
+ ```origin_line_name``` and ```origin_line_name_short``` are the fields that have the route filter applied, if present. For buses they are usually the same, but for trains and ferries they generally show the full and short line names. Both fields are checked and if either meet the filter then the journey is returned.
63
+
47
64
  Fun fact: TransportNSW's raw API output calls itself JSON, but it uses single quotes for strings in defiance of the JSON standards. When using this wrapper the output is formatted such that `jq`, for example, is happy with it.
48
65
 
49
66
  * due: the time (in minutes) before the journey starts
@@ -62,7 +79,8 @@ Description: # TransportNSWv2
62
79
  * latitude & longitude: The location of the vehicle, if available
63
80
 
64
81
  Please note that the origin and destination detail is just that - information about the first and last stops on the journey at the time the request was made. We don't return any intermediate steps, transport change types etc other than the total number of changes - the assumption is that you'll know the details of your specified trip, you just want to know when the next departure is. If you need much more detailed information then I recommend that you use the full Transport NSW trip planner website or application.
65
- Also note that the 'transport_type' filter, if present, only makes sure that at least one leg of the journey includes that transport type.
82
+
83
+ Also note that the 'transport_type' filter, if present, only makes sure that at least one leg of the journey includes that transport type unless 'strict_transport_type' is True, in which case the first leg MUST be of the requested type to be returned.
66
84
 
67
85
  ## Thank you
68
86
  Thank you Dav0815 for your TransportNSW library that the vast majority of this fork is based on. I couldn't have done it without you!
@@ -8,7 +8,7 @@ An OpenData account and API key is required to request the data. More informatio
8
8
  https://opendata.transport.nsw.gov.au/user-guide. You need to register an application that needs both the Trip Planner and Realtime Vehicle Positions APIs
9
9
 
10
10
  ### Get the stop IDs
11
- The function needs the stop IDs for the source and destination, and optionally how many minutes from now the departure should be, and if you want to filter trips by a specific transport type. The easiest way to get the stop ID is via https://transportnsw.info/stops#/. It provides the option to search for either a location or a specific platform, bus stop or ferry wharf. Regardless of if you specify a general location for the origin or destination, the return information shows the stop_id for the actual arrival and destination platform, bus stop or ferry wharf.
11
+ The function needs the stop IDs for the source and destination, and optionally how many minutes from now the departure should be, and if you want to filter trips by a specific transport type, or to only include trips that have specific text somewhere in the line/service details (see below). The easiest way to get the stop ID is via https://transportnsw.info/stops#/. It provides the option to search for either a location or a specific platform, bus stop or ferry wharf. Regardless of if you specify a general location for the origin or destination, the return information shows the stop_id for the actual arrival and destination platform, bus stop or ferry wharf.
12
12
 
13
13
  If it's available, the general occupancy level and the latitude and longitude of the selected journey's vehicle (train, bus, etc) will be returned.
14
14
 
@@ -17,7 +17,21 @@ The source API details can be found here: https://opendata.transport.nsw.gov.au/
17
17
 
18
18
  ### Parameters
19
19
  ```python
20
- .get_trip(origin_stop_id, destination_stop_id, api_key, [trip_wait_time = 0], [transport_type = 0])
20
+ .get_trip(origin_stop_id, destination_stop_id, api_key, [trip_wait_time = 0], [transport_type = 0], [strict_transport_type = True|False], [raw_output = True|False], [journeys_to_return = 1], [route_filter = ''] )
21
+ ```
22
+
23
+ Transport types:
24
+ ```
25
+ 1: Train
26
+ 2: Metro
27
+ 4: Light rail
28
+ 5: Bus
29
+ 7: Coach
30
+ 9: Ferry
31
+ 11: School bus
32
+ 99: Walk
33
+ 100: Walk
34
+ 107: Cycle
21
35
  ```
22
36
 
23
37
  TransportNSW's trip planner can work better if you use the general location IDs (eg Central Station) rather than a specific Stop ID (eg Central Station, Platform 19) for the destination, depending on the transport type. Forcing a specific end destination sometimes results in much more complicated trips. Also note that the API expects (and returns) the Stop IDs as strings, although so far they all appear to be numeric.
@@ -37,6 +51,9 @@ print(journey)
37
51
  ```python
38
52
  {"due": 3, "origin_stop_id": "207537", "origin_name": "Mona Vale Rd at Shinfield Ave, St Ives", "departure_time": "2024-05-20T21:59:48Z", "destination_stop_id": "2000338", "destination_name": "Central Station, Platform 18, Sydney", "arrival_time": "2024-05-20T22:47:36Z", "origin_transport_type": "Bus", "origin_transport_name": "Sydney Buses Network", "origin_line_name": "195", "origin_line_name_short": "195", "changes": 1, "occupancy": "MANY_SEATS", "real_time_trip_id": "2096551", "latitude": -33.72665786743164, "longitude": 151.16305541992188}
39
53
  ```
54
+
55
+ ```origin_line_name``` and ```origin_line_name_short``` are the fields that have the route filter applied, if present. For buses they are usually the same, but for trains and ferries they generally show the full and short line names. Both fields are checked and if either meet the filter then the journey is returned.
56
+
40
57
  Fun fact: TransportNSW's raw API output calls itself JSON, but it uses single quotes for strings in defiance of the JSON standards. When using this wrapper the output is formatted such that `jq`, for example, is happy with it.
41
58
 
42
59
  * due: the time (in minutes) before the journey starts
@@ -55,7 +72,8 @@ Fun fact: TransportNSW's raw API output calls itself JSON, but it uses single q
55
72
  * latitude & longitude: The location of the vehicle, if available
56
73
 
57
74
  Please note that the origin and destination detail is just that - information about the first and last stops on the journey at the time the request was made. We don't return any intermediate steps, transport change types etc other than the total number of changes - the assumption is that you'll know the details of your specified trip, you just want to know when the next departure is. If you need much more detailed information then I recommend that you use the full Transport NSW trip planner website or application.
58
- Also note that the 'transport_type' filter, if present, only makes sure that at least one leg of the journey includes that transport type.
75
+
76
+ Also note that the 'transport_type' filter, if present, only makes sure that at least one leg of the journey includes that transport type unless 'strict_transport_type' is True, in which case the first leg MUST be of the requested type to be returned.
59
77
 
60
78
  ## Thank you
61
79
  Thank you Dav0815 for your TransportNSW library that the vast majority of this fork is based on. I couldn't have done it without you!
@@ -71,7 +71,7 @@ class TransportNSWv2(object):
71
71
  }
72
72
 
73
73
  def get_trip(self, name_origin, name_destination , api_key, journey_wait_time = 0, transport_type = 0, \
74
- strict_transport_type = False, raw_output = False, journeys_to_return = 1):
74
+ strict_transport_type = False, raw_output = False, journeys_to_return = 1, route_filter = ''):
75
75
  """Get the latest data from Transport NSW."""
76
76
  fmt = '%Y-%m-%dT%H:%M:%SZ'
77
77
 
@@ -83,6 +83,7 @@ class TransportNSWv2(object):
83
83
  self.strict_transport_type = strict_transport_type
84
84
  self.raw_output = raw_output
85
85
  self.journeys_to_return = journeys_to_return
86
+ self.route_filter = route_filter
86
87
 
87
88
  # This query always uses the current date and time - but add in any 'journey_wait_time' minutes
88
89
  now_plus_wait = datetime.now() + timedelta(minutes = journey_wait_time)
@@ -141,19 +142,14 @@ class TransportNSWv2(object):
141
142
  no_valid_journeys = False
142
143
 
143
144
  for current_journey_index in range (0, retrieved_journeys, 1):
144
- if transport_type == 0:
145
- # Just grab the next trip
146
- journey = result['journeys'][current_journey_index]
147
- next_journey_index = current_journey_index + 1
148
- else:
149
- # Look for a trip with a matching class filter in at least one of its legs. Either ANY, or the first leg, depending on how strict we're being
150
- journey, next_journey_index = self.find_next_journey(result['journeys'], current_journey_index, transport_type, strict_transport_type)
145
+ # Look for a trip with a matching transport type filter in at least one of its legs. Either ANY, or the first leg, depending on how strict we're being
146
+ journey, next_journey_index = self.find_next_journey(result['journeys'], current_journey_index, transport_type, strict_transport_type, route_filter)
151
147
 
152
148
  if ((journey is None) or (journey['legs']) is None):
153
149
  pass
154
150
  else:
155
151
  legs = journey['legs']
156
- first_leg = self.find_first_leg(legs, transport_type, strict_transport_type)
152
+ first_leg = self.find_first_leg(legs, transport_type, strict_transport_type, route_filter)
157
153
 
158
154
  #Executive decision - don't be strict on the last leg, there's often some walking (transport type 100) involved.
159
155
  last_leg = self.find_last_leg(legs, transport_type, False)
@@ -178,8 +174,8 @@ class TransportNSWv2(object):
178
174
  destination_arrival_time = destination['arrivalTimeEstimated']
179
175
 
180
176
  # Origin type info - train, bus, etc
181
- origin_mode_temp = transportation['product']['class']
182
- origin_mode = self.get_mode(origin_mode_temp)
177
+ #origin_mode_temp = transportation['product']['class']
178
+ origin_mode = self.get_mode(transportation['product']['class'])
183
179
  origin_mode_name = transportation['product']['name']
184
180
 
185
181
  # RealTimeTripID info so we can try and get the current location later
@@ -209,79 +205,75 @@ class TransportNSWv2(object):
209
205
  longitude = 'n/a'
210
206
 
211
207
  if realtimetripid != 'n/a':
212
- # Build the URL
213
- url = \
214
- 'https://api.transport.nsw.gov.au/v1/gtfs/vehiclepos' \
215
- + self.get_url(origin_mode)
216
- auth = 'apikey ' + self.api_key
217
- header = {'Authorization': auth}
218
-
219
- response = requests.get(url, headers=header, timeout=10)
220
- # Only try and process the results if we got a good return code
221
- if response.status_code == 200:
222
- # Search the feed and see if we can find the trip_id
223
- # If we do, capture the latitude and longitude
224
- feed = gtfs_realtime_pb2.FeedMessage()
225
- feed.ParseFromString(response.content)
226
-
227
- # Unfortunately we need to do some mucking about for train-based trip_ids
228
- # Define the appropriate regular expression to search for - usually just the full text
229
- bFindLocation = True
230
-
231
- if origin_mode == 'Train':
232
- triparray = realtimetripid.split('.')
233
- if len(triparray) == 7:
234
- trip_id_wild = triparray[0] + '.' + triparray[1] + '.' + triparray[2] + '.+.' + triparray[4] + '.' + triparray[5] + '.' + triparray[6]
235
- else:
236
- # Hmm, it's not the right length (this happens rarely) - give up
237
- bFindLocation = False
238
- else:
239
- trip_id_wild = realtimetripid
240
-
241
- if bFindLocation:
242
- reg = re.compile(trip_id_wild)
208
+ # Build the URL(s) - some modes have multiple GTFS sources, unforunately
209
+ url_path = self.get_url(origin_mode)
210
+ url_list = self.get_url_path(origin_mode)
211
+ bFoundTripID = False
212
+
213
+ for mode_url in url_list:
214
+ url = url_path + mode_url
215
+ auth = 'apikey ' + self.api_key
216
+ header = {'Authorization': auth}
217
+
218
+ response = requests.get(url, headers=header, timeout=10)
219
+
220
+ # Only try and process the results if we got a good return code
221
+ if response.status_code == 200:
222
+ # Search the feed and see if we can match realtimetripid to trip_id
223
+ # If we do, capture the latitude and longitude
224
+ feed = gtfs_realtime_pb2.FeedMessage()
225
+ feed.ParseFromString(response.content)
226
+
227
+ reg = re.compile(realtimetripid)
243
228
 
244
229
  for entity in feed.entity:
245
230
  if bool(re.match(reg, entity.vehicle.trip.trip_id)):
246
231
  latitude = entity.vehicle.position.latitude
247
232
  longitude = entity.vehicle.position.longitude
248
- # We found it, so break out
233
+
234
+ # We found it, so flag it and break out
235
+ bFoundTripID = True
249
236
  break
250
237
 
251
- self.info = {
252
- ATTR_DUE_IN: due,
253
- ATTR_ORIGIN_STOP_ID : origin_stop_id,
254
- ATTR_ORIGIN_NAME : origin_name,
255
- ATTR_DEPARTURE_TIME : origin_departure_time,
256
- ATTR_DESTINATION_STOP_ID : destination_stop_id,
257
- ATTR_DESTINATION_NAME : destination_name,
258
- ATTR_ARRIVAL_TIME : destination_arrival_time,
259
- ATTR_ORIGIN_TRANSPORT_TYPE : origin_mode,
260
- ATTR_ORIGIN_TRANSPORT_NAME: origin_mode_name,
261
- ATTR_ORIGIN_LINE_NAME : origin_line_name,
262
- ATTR_ORIGIN_LINE_NAME_SHORT : origin_line_name_short,
263
- ATTR_CHANGES: changes,
264
- ATTR_OCCUPANCY : occupancy,
265
- ATTR_REAL_TIME_TRIP_ID : realtimetripid,
266
- ATTR_LATITUDE : latitude,
267
- ATTR_LONGITUDE : longitude
268
- }
269
-
270
- found_journeys = found_journeys + 1
271
-
272
- # Add to the return array
273
- if (no_valid_journeys == True):
274
- break
275
-
276
- if (found_journeys >= 2):
277
- json_output = json_output + ',' + json.dumps(self.info)
278
- else:
279
- json_output = json_output + json.dumps(self.info)
280
-
281
- if (found_journeys == journeys_to_return):
282
- break
283
-
284
- current_journey_index = next_journey_index
238
+ if bFoundTripID == True:
239
+ # No need to look any further
240
+ break
241
+
242
+
243
+ self.info = {
244
+ ATTR_DUE_IN: due,
245
+ ATTR_ORIGIN_STOP_ID : origin_stop_id,
246
+ ATTR_ORIGIN_NAME : origin_name,
247
+ ATTR_DEPARTURE_TIME : origin_departure_time,
248
+ ATTR_DESTINATION_STOP_ID : destination_stop_id,
249
+ ATTR_DESTINATION_NAME : destination_name,
250
+ ATTR_ARRIVAL_TIME : destination_arrival_time,
251
+ ATTR_ORIGIN_TRANSPORT_TYPE : origin_mode,
252
+ ATTR_ORIGIN_TRANSPORT_NAME: origin_mode_name,
253
+ ATTR_ORIGIN_LINE_NAME : origin_line_name,
254
+ ATTR_ORIGIN_LINE_NAME_SHORT : origin_line_name_short,
255
+ ATTR_CHANGES: changes,
256
+ ATTR_OCCUPANCY : occupancy,
257
+ ATTR_REAL_TIME_TRIP_ID : realtimetripid,
258
+ ATTR_LATITUDE : latitude,
259
+ ATTR_LONGITUDE : longitude
260
+ }
261
+
262
+ found_journeys = found_journeys + 1
263
+
264
+ # Add to the return array
265
+ if (no_valid_journeys == True):
266
+ break
267
+
268
+ if (found_journeys >= 2):
269
+ json_output = json_output + ',' + json.dumps(self.info)
270
+ else:
271
+ json_output = json_output + json.dumps(self.info)
272
+
273
+ if (found_journeys == journeys_to_return):
274
+ break
275
+
276
+ current_journey_index = next_journey_index
285
277
 
286
278
  json_output='{"journeys_to_return": ' + str(self.journeys_to_return) + ', "journeys_with_data": ' + str(found_journeys) + ', "journeys": [' + json_output + ']}'
287
279
  return json_output
@@ -299,8 +291,8 @@ class TransportNSWv2(object):
299
291
  # return None
300
292
 
301
293
 
302
- def find_next_journey(self, journeys, start_journey_index, journeytype, strict):
303
- # Fnd the next journey that has a leg of the requested type
294
+ def find_next_journey(self, journeys, start_journey_index, journeytype, strict, route_filter):
295
+ # Fnd the next journey that has a leg of the requested type, and/or that satisfies the route filter
304
296
  journey_count = len(journeys)
305
297
 
306
298
  # Some basic error checking
@@ -308,7 +300,7 @@ class TransportNSWv2(object):
308
300
  return None, None
309
301
 
310
302
  for journey_index in range (start_journey_index, journey_count, 1):
311
- leg = self.find_first_leg(journeys[journey_index]['legs'], journeytype, strict)
303
+ leg = self.find_first_leg(journeys[journey_index]['legs'], journeytype, strict, route_filter)
312
304
  if leg is not None:
313
305
  return journeys[journey_index], journey_index + 1
314
306
  else:
@@ -318,22 +310,32 @@ class TransportNSWv2(object):
318
310
  return None, None
319
311
 
320
312
 
321
- def find_first_leg(self, legs, legtype, strict):
313
+ def find_first_leg(self, legs, legtype, strict, route_filter):
322
314
  # Find the first leg of the requested type
323
315
  leg_count = len(legs)
324
316
  for leg_index in range (0, leg_count, 1):
325
- leg_class = legs[leg_index]['transportation']['product']['class']
326
- # We've got a filter, and the leg type matches it, so return that leg
327
- if legtype != 0 and leg_class == legtype:
328
- return legs[leg_index]
317
+ #First, check against the route filter
318
+ origin_line_name_short = 'n/a'
319
+ origin_line_name = 'n/a'
329
320
 
330
- # We don't have a filter, and this is the first non-walk/cycle leg so return that leg
331
- if legtype == 0 and leg_class < 99:
332
- return legs[leg_index]
321
+ if 'transportation' in legs[leg_index]:
322
+ if 'disassembledName' in legs[leg_index]['transportation']:
323
+ origin_line_name_short = legs[leg_index]['transportation']['disassembledName']
324
+ origin_line_name = legs[leg_index]['transportation']['number']
333
325
 
334
- # Exit if we're doing strict filtering and we haven't found that type in the first leg
335
- if legtype != 0 and strict == True:
336
- return None
326
+ if (route_filter in origin_line_name_short or route_filter in origin_line_name):
327
+ leg_class = legs[leg_index]['transportation']['product']['class']
328
+ # We've got a filter, and the leg type matches it, so return that leg
329
+ if legtype != 0 and leg_class == legtype:
330
+ return legs[leg_index]
331
+
332
+ # We don't have a filter, and this is the first non-walk/cycle leg so return that leg
333
+ if legtype == 0 and leg_class < 99:
334
+ return legs[leg_index]
335
+
336
+ # Exit if we're doing strict filtering and we haven't found that type in the first leg
337
+ if legtype != 0 and strict == True:
338
+ return None
337
339
 
338
340
  # Hmm, we didn't find one
339
341
  return None
@@ -378,6 +380,7 @@ class TransportNSWv2(object):
378
380
  """Map the iconId to a full text string"""
379
381
  modes = {
380
382
  1: "Train",
383
+ 2: "Metro",
381
384
  4: "Light rail",
382
385
  5: "Bus",
383
386
  7: "Coach",
@@ -389,17 +392,35 @@ class TransportNSWv2(object):
389
392
  }
390
393
  return modes.get(iconId, None)
391
394
 
392
-
393
395
  def get_url(self, mode):
394
- """Map the journey mode to the proper real time location URL """
396
+ """Map the journey mode to the proper base real time location URL """
397
+ v1_url = "https://api.transport.nsw.gov.au/v1/gtfs/vehiclepos"
398
+ v2_url = "https://api.transport.nsw.gov.au/v2/gtfs/vehiclepos"
399
+
400
+ url_options = {
401
+ "Train": v2_url,
402
+ "Metro": v2_url,
403
+ "Light rail": v1_url,
404
+ "Bus": v1_url,
405
+ "Coach": v1_url,
406
+ "Ferry": v1_url,
407
+ "School bus": v1_url
408
+ }
409
+ return url_options.get(mode, None)
410
+
411
+
412
+ def get_url_path(self, mode):
413
+ """Map the journey mode to the proper modifier URL """
414
+ bus_list = ["/buses", "/regionbuses/centralwestandorana", "/regionbuses/centralwestandorana2", "/regionbuses/newenglandnorthwest", "/regionbuses/northcoast", "/regionbuses/northcoast2", "/regionbuses/northcoast3", "/regionbuses/riverinamurray", "/regionbuses/riverinamurray2", "/regionbuses/southeasttablelands", "/regionbuses/southeasttablelands2", "/regionbuses/sydneysurrounds", "/regionbuses/newcastlehunter", "/regionbuses/farwest"]
395
415
 
396
416
  url_options = {
397
- "Train" : "/sydneytrains",
398
- "Light rail" : "/lightrail/innerwest",
399
- "Bus" : "/buses",
400
- "Coach" : "/buses",
401
- "Ferry" : "/ferries/sydneyferries",
402
- "School bus" : "/buses"
417
+ "Train" : ["/sydneytrains"],
418
+ "Metro" : ["/metro"],
419
+ "Light rail" : ["/lightrail/innerwest", "/lightrail/cbdandsoutheast", "/lightrail/newcastle"],
420
+ "Bus" : bus_list,
421
+ "Coach" : bus_list,
422
+ "Ferry" : ["/ferries/sydneyferries"],
423
+ "School bus" : bus_list
403
424
  }
404
425
  return url_options.get(mode, None)
405
426
 
@@ -5,7 +5,7 @@ with open("README.md", "r") as fh:
5
5
 
6
6
  setuptools.setup(
7
7
  name="PyTransportNSWv2",
8
- version="0.5.6",
8
+ version="0.6.5",
9
9
  author="andystewart999",
10
10
  description="Get detailed per-trip transport information from TransportNSW",
11
11
  long_description=long_description,