def getDirectConnection(origin_id, destination_id): #--------------------------------------------------------------------------- # checks for direct connections from tart_id to stop_id and returns # a list of entries [line, destination] #--------------------------------------------------------------------------- direct_connections = [] connections = get_routedata(origin_id, destination_id) if connections == None: return [] if 'resultList' not in connections: return direct_connections for journey in connections['resultList']: if 'elementList' not in journey: continue if len(journey['elementList']) != 1: myask_log.debug( 7, "connection found with '" + str(len(journey['elementList'])) + "' legs. ignoring") else: con = {} leg = journey['elementList'][0] try: con['lineName'] = leg['lineName'] con['tripId'] = leg['tripId'] con['destinationName'] = leg['destinationName'] direct_connections.append(con) except: myask_log.debug(3, "fields missing") return direct_connections
def get_stoppoint(name): parameter = {'searchString': name, 'maxResults': 5, 'searchTypes': 'STOPPOINT'} request = requests.get(baseurl.format(url_l), params=parameter) if request.status_code != 200: raise Exception if request.headers['content-type'] != 'application/json;charset=UTF-8': raise Exception data = request.json() resultstops = [] print (u"DEBUG: got request \n"+ str(data) + "\n--------------") if data['resultCount'] == 0: myask_log.debug(3, u"No result for stop name {}".format(name)) elif data['resultCount'] > 1: print("More than one result for stop name {}:".format(name)) print("ID\tName") for elem in data['resultList']: stopid = elem['stopPointId'] stopname = unicodify(elem['stopPointName']) resultstops.append([stopid,stopname]) else: # a single result was shown stopid = data['resultList'][0]['stopPointId'] stopname = unicodify(data['resultList'][0]['stopPointName']) myask_log.debug(3, u"Found a single match for '"+name+"': "+str(stopid) +" : "+stopname) resultstops.append([stopid,stopname]) return resultstops
def process_FindConnectionFromOther(slots, appdef, user_profile): #--------------------------------------------------------------------------- # Lists connections from a specific station to a specific station # # Intent: 'FindConnection' # Slots: # - "Origin" station to which connections should be found # - "OriginCity" # - "Destination" station to which connections should be found # - "DestinationCity" # "Busline" : list only buses for a specific line # "Next" : (future) List only next or next N connections # "Transport" : Filter by Mode of Transport: Bus, Train, Direct # Origin is set to the user's default sstation #--------------------------------------------------------------------------- myask_log.debug(3, "Got intent FindConnectionFromOther") # convert all times to localtime, independent of the AWS server location #----------------------------------------------------------------------- # get ID for origin stop #----------------------------------------------------------------------- if 'Origin' not in slots: if user_profile.isKnownUser(): # user favorite as fall-back slots['qorg_id'] = ToInt(user_profile.GetDefaultStopId()) else: return bus_response.out_OriginMissing(slots, appdef, user_profile) else: slots['qorg_id'] = ToInt(slots['Origin']) if slots['qorg_id'] < 10000: return bus_response.out_InvalidOrigin(slots['Origin'], slots, appdef, user_profile) #------------------------------------------------------------------------- # fill destination ID #------------------------------------------------------------------------- if 'Destination' in slots: destination_id = ToInt(slots["Destination"]) destination_str = slots["Destination"] elif 'qdest_id' in slots: # check if there is a station from the dialog context to re-use destination_id = ToInt(slots['qdest_id']) destination_str = "" else: # no information found. Use default location from user profile return bus_response.out_DestinationMissing(slots, appdef, user_profile) if int(destination_id) < 10000: myask_log.warning("Invalid stop id for destination station:" + str(destination_id)) return bus_response.out_InvalidDestination(destination_str, slots, appdef, user_profile) # we got a single result slots['qdest_id'] = destination_id return _FetchConnections(slots, appdef, user_profile)
def process_FindConnectionFromFavorite(slots, appdef, user_profile): #--------------------------------------------------------------------------- # Lists connections to a specific station from the user's default station # # Intent: 'FindConnectionFromFavorite' # Slots: # - "Destination" station to which connections should be found # - "DestinationCity" # "Busline" : list only buses for a specific line # "Next" : (future) List only next or next N connections # "Transport" : Filter by Mode of Transport: Bus, Train, Direct # Origin is set to the user's default sstation #--------------------------------------------------------------------------- myask_log.debug(3, "Got intent FindConnectionFromFavorite") #----------------------------------------------------------------------- # fill origin ID from user profile #----------------------------------------------------------------------- if user_profile.isKnownUser(): slots['qorg_id'] = ToInt(user_profile.GetDefaultStopId()) else: return bus_response.out_PromptUserProfileNeeded(slots) #------------------------------------------------------------------------- # fill destination ID #------------------------------------------------------------------------- if 'Destination' in slots: destination_id = ToInt(slots["Destination"]) destination_str = slots["Destination"] elif 'qdest_id' in slots: # check if there is a station from the dialog context to re-use destination_id = ToInt(slots['qdest_id']) destination_str = "" else: # no information found. Use default location from user profile return bus_response.out_DestinationMissing(slots, appdef, user_profile) myask_log.debug(5, "Got destination ID " + str(destination_id)) if int(destination_id) < 10000: myask_log.warning("Invalid stop id for destination station:" + str(destination_id)) if 'Destination.literal' in slots: return bus_response.out_InvalidDestination( slots["Destination.literal"], slots, appdef, user_profile) else: return bus_response.out_InvalidDestination(destination_str, slots, appdef, user_profile) # we got a single result slots['qdest_id'] = destination_id return _FetchConnections(slots, appdef, user_profile)
def process_GetDeparturesFromOther(slots, appdef, user_profile): #-------------------------------------------------------------------------- # Shows live departures from a specific station 'origin' # # Intent: 'Departures' # Slots: # "Origin" : station from which the departures are requested # "Direction" : lists only inbound / outbound buses # "Busline" : list only buses for a specific line # "Next" : (future) List only next or next N connections # "Transport" : FIlter by Mode of Transport: Bus, Train, Direct #-------------------------------------------------------------------------- myask_log.debug(3, "Got intent 'GetDeparturesFromOther'") # convert all times to localtime, independent of the AWS server location if 'utc_offset' in slots: utc_offset = slots['utc_offset'] else: utc_offset = 0 if 'Busline' in slots and slots['Busline'] != "?": linefilter = slots['Busline'] else: linefilter = '' if "Direction" in slots: direction = slots["Direction"] else: direction = "" #----------------------------------------------------------------------- # get ID for origin stop #----------------------------------------------------------------------- if 'Origin' not in slots: myask_log.debug(5, "Slot 'Origin' missing in GetDeparturesFromOther...") if user_profile.HasDefaultStop(): # user favorite as fall-back slots['qorg_id'] = ToInt(user_profile.GetDefaultStopId()) myask_log.debug(5, "...Using user profile default instead") else: myask_log.debug(5, "...and no default stop found in user profile") return bus_response.out_OriginMissing(slots, appdef, user_profile) else: slots['qorg_id'] = ToInt(slots['Origin']) if slots['qorg_id'] < 10000: if 'Origin.literal' in slots['Origin.literal']: return bus_response.out_InvalidOrigin(slots['Origin.literal'], slots, appdef, user_profile) else: return bus_response.out_InvalidOrigin('', slots, appdef, user_profile) else: results = aseag_api.GetDepartures(slots['qorg_id'], linefilter, direction, utc_offset) return bus_response.out_Departures(results, slots, appdef, user_profile) # if we are here, something went wrong return bus_response.out_ImplementationError("GetDeparturesFromOther", slots, appdef, user_profile)
def _FetchConnections(slots, appdef, user_profile): #-------------------------------------------------------------------------- # Finds connections from one bus stop to another # # Requires the following slots to be set: # 'qorg_id' bus stop ID for the origin stop # 'qdest_is' bus stop ID for the destination stop # Optional slots (used to filter the results= # "Busline" : list only this buses for a specific line # "Next" : (future) List only next or next N connections # "Transport" : (future) Filter by Mode of Transport: Bus, Train, Direct # RETURNS: Alexa output structure #-------------------------------------------------------------------------- if myask_slots.checkslots(slots, ['lang', 'qorg_id', 'qdest_id'], "_FetchConnections") == False: return myask_alexaout.createAlexaErrorOutput( myask_slots.error_slots_missing("_FetchConnections"), slots) myask_log.debug( 3, "In Function _FindConnection " + str(slots['qorg_id']) + "-->" + str(slots['qdest_id'])) # prepare slots for call to aseag API # convert all times to localtime, independent of the AWS server location if 'utc_offset' in slots: utc_offset = slots['utc_offset'] else: utc_offset = 0 if 'Busline' in slots and slots['Busline'] != "?": linefilter = slots['Busline'] else: linefilter = '' if 'Transport' in slots: transport = slots['Transport'] else: transport = "" match, result_connections = aseag_api.GetFilteredConnections( slots['qorg_id'], slots['qdest_id'], linefilter, transport, utc_offset) myask_log.debug(2, "connection results from "+ str(slots['qorg_id'])+ " to " + str(slots['qdest_id'])+ \ "match:" +str(match)+":\n" + str(result_connections)) return bus_response.out_Connections(result_connections, slots, appdef, user_profile)
def __init__(self, userID): self._user_id = userID if userID == "FAKE": #Found profile of "diekellnerfamilie" self._profile_data = HARDCODED_PROFILES['TESTUSER'] else: self._profiletable = myask_dynamodb.dynamoDB("aseag_userprofile") myask_log.debug(0, "GetTable: " + str(self._profiletable.GetStatus())) profile_data = self._profiletable.FetchUserProfile(userID) if profile_data == {}: myask_log.warning( "Could not locate user profile. Creating new one. User: " + str(userID)) self._profiletable.CreateNewUserProfile(userID, {}) self._profile_data = {} else: self._profile_data = profile_data
def GetConnectionsWithBus(origin_ID, destination_ID, busline, utc_offset): #--------------------------------------------------------------------------- # Retrieves connection thet contain a specific busline only. # The system fetches connections from 'origin_ID' to 'destination_ID' using # GetConnections(). # The results are then filtered to only contain connections where # at least one leg uses the specified busline. # If no matches are found at all, the system returns the full list (constraint is relaxed) # PARAMETERS: # - origin_ID: Bus stop ID for the departure station (integer, 1000000-999999) # - destination_ID: Bus stop ID for the departure station (integer, 1000000-999999) # - busline: (int/string) denoting the busline to be filtered for # - utc_offset: Timezone, for which the times should be returned (API uses UTC) # RETURNS: match,connection_list # 'match' (booloean): True if the busline constraint was met, False if it was relaxed # 'connection_list' list of bus connections. See GetConnections() for details #--------------------------------------------------------------------------- connection_list = GetConnections(origin_ID, destination_ID, utc_offset) if busline == 0: return (True, connection_list) print(u"checking for buses"+ str(busline)) matching_connections = [] # check if the buses are indeed used for connection in connection_list: # check if this connection uses the specified buy if 'legs' in connection: usesbus = False for leg in connection['legs']: if 'line' in leg and int(leg['line']) == busline: myask_log.debug(5, u"match found for bus "+str(busline) +\ u" in connection "+str(connection) ) usesbus = True break if usesbus: matching_connections.append(connection) else: myask_log.debug(5, u"NO match found for bus "+str(busline) +\ u" in connection "+str(connection) ) if len(matching_connections) == 0: return (False, connection_list) else: return (True, matching_connections)
def process_GetDeparturesFromFavorite(slots, appdef, user_profile): #-------------------------------------------------------------------------- # Shows live departures from the user's default connection # # Intent: 'DeparturesFromFavorite' # Slots: (used to filter departures) # "Direction" : lists only inbound / outbound buses # "Busline" : list only buses for a specific line # "Next" : (future) List only next or next N connections # "Transport" : FIlter by Mode of Transport: Bus, Train, Direct #-------------------------------------------------------------------------- myask_log.debug(3, "Got intent 'GetDeparturesFromFavorite'") # convert all times to localtime, independent of the AWS server location if 'utc_offset' in slots: utc_offset = slots['utc_offset'] else: utc_offset = 0 if 'Busline' in slots and slots['Busline'] != "?": linefilter = slots['Busline'] else: linefilter = '' if "Direction" in slots: direction = slots["Direction"] else: direction = "" #----------------------------------------------------------------------- # get ID for origin stop from user profile #----------------------------------------------------------------------- if user_profile.isKnownUser(): slots['qorg_id'] = ToInt(user_profile.GetDefaultStopId()) else: return bus_response.out_PromptUserProfileNeeded(slots) if (slots['qorg_id']) < 10000: return bus_response.out_InvalidFavorite(user_profile) results = aseag_api.GetDepartures(slots['qorg_id'], linefilter, direction, utc_offset) return bus_response.out_Departures(results, slots, appdef, user_profile)
def GetDepartures(StopID, busline, direction, utc_offset): #-------------------------------------------------------------------------- # Returns a list of live bus departures from the specified bus stop # PARAMETERS: # - 'StopID' Bus stop ID for the departure station (integer, 1000000-999999) # - 'busline' : (integer/string) Filter to show only buses from that line. # If '0', all buses are shown # - 'direction: (string) Shows only buses for the specified connection # either 'DIR_INWARD_ or 'DIR_OUTWARD' # if "", all departures are shown # # - utc_offset: Timezone, for which the times should be returned (API uses UTC) # RETURNS: # List of departures from the station with: # [ # dep_time, // datetime. Estimated departure time # busnr, // string Bus number # destination, // (string) destination of the bus # ] #-------------------------------------------------------------------------- myask_log.debug( 3, u"aseag_api.GetDepartures: Haltestellenabfrage von " + str(StopID) + u". Buslinie: '" + str(busline) + u"'. Direction: " + str(direction)) if busline == '' or busline == '?': buses = [] else: buses = [str(busline)] output = get_stopdata(StopID, buses) # print "DEPARTURES:-------------------------" # print json.dumps(output, indent=4, sort_keys=False) # print "END_CONNECTION-------------------------------------" connection_list = [] for line in output: myask_log.debug(5, "LINE: " + str(line)) if tsfilter(line[0], totime): dep_time = unix_epoch_to_utcdatetime( line[0]) + datetime.timedelta(hours=utc_offset) busnr = line[1] destination = unicodify(line[2]) # check if the connection matches the filters for busline and direction if MatchesDirection(StopID, direction, busnr, destination): connection = (dep_time, busnr, destination) connection_list.append(connection) else: myask_log.debug( 5, u"Ignoring connection line " + str(busnr) + u" to " + destination + u": does not match direction") myask_log.debug(4, str(len(connection_list)) + u" connections found") return connection_list
def process_ChangeDefaultStation(slots, appdef, user_profile): #--------------------------------------------------------------------------- # Handles a user request to change the default stop # # The system triggers a confirmation question back to the user # if the user answers with "yes" or "no", the function ConfirmChangeDefaultStation is called #--------------------------------------------------------------------------- myask_log.debug(3, "Got intent 'GetFavConnecionDepartures'") if "Origin" not in slots: return bus_response.out_DefaultStationMissing(slots, appdef, user_profile) elif ToInt(slots["Origin"]) < 10000: return bus_response.out_DefaultStationMissing(slots, appdef, user_profile) slotlist = ["Origin"] session_attributes = myask_slots.store_session_slots( "ChangeDefaultStation", slotlist, slots) return bus_response.out_ConfirmChangeFavorite(slots["Origin"], session_attributes, slots, appdef, user_profile)
def on_intent(intent_request, session, appdef, user_profile): #-------------------------------------------------------------------------- # Main intent handler function. # Called when Alexa receives a speech intent """ Called when the user specifies an intent for this skill """ myask_log.debug( 5, "on_intent requestId=" + intent_request['requestId'] + ", sessionId=" + session['sessionId']) intent = intent_request['intent'] current_intent = intent_request['intent']['name'] input_locale = intent_request['locale'] myask_log.debug(2, "Got user profile: " + str(user_profile.GetProfile())) if current_intent in ["AMAZON.YesIntent", "AMAZON.NoIntent"]: slots = myask_slots.parse_slots(intent, session, True, input_locale, appdef) if current_intent == "AMAZON.YesIntent": slots["Confirmed"] = True elif current_intent == "AMAZON.NoIntent": slots["Confirmed"] = False if 'prev_intent' in slots: if slots["prev_intent"] == "ChangeDefaultStation": return ConfirmChangeDefaultStation(slots, appdef, user_profile) else: myask_alexaout.createAlexaErrorOutput( "Oops, da ist was schiefgelaufen") else: myask_alexaout.createAlexaErrorOutput( "Sorry, das habe ich nicht verstanden") slots = myask_slots.parse_slots(intent, session, False, input_locale, appdef) slots['current_intent'] = current_intent #Now process the intent via the appropriate function myask_log.debug(3, "Handling current_intent='" + str(current_intent) + "'") if current_intent == "GetDeparturesFromFavorite": return process_GetDeparturesFromFavorite(slots, appdef, user_profile) elif current_intent == "GetDeparturesFromOther": return process_GetDeparturesFromOther(slots, appdef, user_profile) elif current_intent == "GetFavConnecionDepartures": return process_GetFavConnecionDepartures(slots, appdef, user_profile) elif current_intent == "FindConnectionFromFavorite": return process_FindConnectionFromFavorite(slots, appdef, user_profile) elif current_intent == "FindConnectionFromOther": return process_FindConnectionFromOther(slots, appdef, user_profile) elif current_intent == "ChangeDefaultStation": return process_ChangeDefaultStation(slots, appdef, user_profile) elif current_intent == "DeleteProfile": return process_DeleteProfile(slots, appdef, user_profile) elif current_intent == "AMAZON.HelpIntent": return bus_response.out_Help(user_profile) elif current_intent == "AMAZON.CancelIntent" or current_intent == "AMAZON.StopIntent": return bus_response.out_SessionEnd() else: raise ValueError("Invalid intent")
def FindFavoriteConnetions(start_id, stop_id, start_time, end_time, preferred_bus, utc_offset): match, lineconnections = GetConnectionsWithBus(start_id, stop_id, preferred_bus, utc_offset) if match and start_time != "": # filter for time window only if there is a bus match matching_connections = [] if re.match("\d\d:\d\d$", start_time): tmp = datetime.datetime.strptime(start_time, "%H:%M") window_start = tmp.time() else: myask_log.error( u"Invalid start time format in 'FindFavoriteConnetions': " + start_time) start_time = datetime.datetime.utcnow() + datetime.timedelta( hours=utc_offset) if (end_time == ""): window_end = window_start + datetime.timedelta(hours=1) elif re.match("\d\d:\d\d$", end_time): tmp = datetime.datetime.strptime(end_time, "%H:%M") window_end = tmp.time() else: myask_log.error( u"Invalid end time format in 'FindFavoriteConnetions': " + end_time) window_end = window_start + datetime.timedelta(hours=1) # now loop over all connections and check if they depart in the right time window for connection in lineconnections: # check if this connection departs in the specified time deptime = connection['start_datetime'].time() if (deptime >= window_start and deptime <= window_end): myask_log.debug(5, u"time match in connection " + str(connection)) matching_connections.append(connection) else: myask_log.debug( 5, u"NO time match in connection " + str(connection)) if len(matching_connections) == 0: myask_log.debug( 5, u"No matchin connections in timewondow found. Returning all") return (False, lineconnections) else: return (True, matching_connections) else: return match, lineconnections
def ConfirmChangeDefaultStation(slots, appdef, user_profile): #--------------------------------------------------------------------------- # Handles confirmation of change of default slot # slot "Confirmed" contains the user answer #--------------------------------------------------------------------------- if myask_slots.checkslots(slots, ['lang', 'Confirmed'], "ConfirmChangeDefaultStation") == False: return myask_alexaout.createAlexaErrorOutput( myask_slots.error_slots_missing("ConfirmChangeDefaultStation"), slots) myask_log.debug(3, "Got command 'ConfirmChangeDefaultStation'") if "Origin" in slots: new_default_id = slots["Origin"] else: myask_log.error( "ConfirmChangeDefaultStation called without slot 'Origin'. How could this happen?" ) new_default_id = user_profile.GetDefaultStopId() if slots["Confirmed"] == True: # user confirmed myask_log.debug(5, "User has confirmed selection of new default station") myask_log.debug(2, "New default station is " + str(new_default_id)) result = user_profile.SetDefaultStopId(new_default_id) if result: myask_log.debug(1, "New favorite set successfully") else: myask_log.error("New favorite could not be set") return bus_response.out_DefaultChanged(slots, appdef, user_profile) else: # user did not confirm return bus_response.out_DefaultChangeCancelled(slots, appdef, user_profile) # if we are here, something went wrong return bus_response.out_ImplementationError( "process_GetFavConnecionDepartures", slots, appdef, user_profile)
def process_GetFavConnecionDepartures(slots, appdef, user_profile): #-------------------------------------------------------------------------- # shows departures a favorite connection from the uer's user profile # # Intent: 'GetFavConnecionDepartures' # Slot: 'FavConnection' identifier for a favorite connection from the user profile # A favorite connection (slot '') from the user profile provides # - departure station # - destination station # - preferred busline (optional) # - preferred time-window (optional) #-------------------------------------------------------------------------- myask_log.debug(3, "Got intent 'GetFavConnecionDepartures'") if 'FavConnection' not in slots: return bus_response.out_FavoriteConnectionMissing( slots, appdef, user_profile) else: fav_connection = user_profile.GetFavoriteConnection( slots["FavConnection"]) if len(fav_connection) == 0: return bus_response.out_FavoriteConnectionNotInUserProfile( slots["FavConnection"], slots, appdef, user_profile) else: # favorite connection found if "OrgID" not in fav_connection or "DestID" not in fav_connection: myask_log.warning( "No StartID or StopID found in FavoriteConnection '" + slots["FavConnection"] + "' for user ") return bus_response.out_InvalidFavoriteConnection( slots, appdef, user_profile) else: if "PreferredLines" in fav_connection: linefilter = fav_connection["PreferredLine"] else: linefilter = '' if "DepTimeWindowStart" in fav_connection: start_time = fav_connection["DepTimeWindowStart"] else: start_time = "" if "DepTimeWindowEnd" in fav_connection: end_time = fav_connection["DepTimeWindowEnd"] else: end_time = "" if 'utc_offset' in slots: utc_offset = slots['utc_offset'] else: utc_offset = 0 (match, result_connections) = aseag_api.FindFavoriteConnetions( fav_connection["OrgID"], fav_connection["DestID"], start_time, end_time, linefilter, utc_offset) # put it in the normal fields for smooth output slots['qorg_id'] = ToInt(fav_connection["OrgID"]) slots['qdest_id'] = ToInt(fav_connection["DestID"]) if linefilter != '': slots['Busline'] = str(linefilter) return bus_response.out_FavoriteConnection( match, result_connections, slots, appdef, user_profile) # if we are here, something went wrong return bus_response.out_ImplementationError( "process_GetFavConnecionDepartures", slots, appdef, user_profile)
def MatchesDirection(station_ID, direction, line, destination): #--------------------------------------------------------------------------- # checks if a given connection matches the list of specified direction # # PARAMETERS # 'station' station ID for a bus stop # 'direction': either 'DIR_INWARD_ or 'DIR_OUTWARD' # 'line' : line of the connection under investigation # 'destination' destination station of the connection under investigation # # RETURNS True if the bus goes in the requested direction # If no valid direction is specified or the bus direction cannot be # determined, the function returns True #--------------------------------------------------------------------------- if direction == "": return True # if there's no direction, everything matches key = str(station_ID) if key in aseag_data.HARDCODED_DIRECTIONS: inwardlist = aseag_data.HARDCODED_DIRECTIONS[key]["inward"] outwardlist = aseag_data.HARDCODED_DIRECTIONS[key]["outward"] else: inwardlist = aseag_data.HARDCODED_DIRECTIONS["DEFAULT"]["inward"] outwardlist = aseag_data.HARDCODED_DIRECTIONS["DEFAULT"]["outward"] busline = int(line) if direction == "DIR_INWARD": # positive list: for (itemid, itemdest) in inwardlist: if destination == itemdest: # the destination is in the list if itemid == 0 or itemid == busline: # the destination matches for all buses or the bus is the right one myask_log.debug(10, u"Match: Found inbound match for station '"+key+u"' Bus "+str(busline)+ ": "+destination) return True # negative list let's check if the item is in the outbound list for (itemid, itemdest) in outwardlist: if destination == itemdest: # the destination is in the list if itemid == 0 or itemid == busline: # the destination matches for all buses or the bus is the right one myask_log.debug(10, u"Mismatch: Found outbound match for station '"+key+u"' Bus "+str(busline)+ ": "+destination) return False myask_log.debug(10, u"Did not find in/out match for '"+key+u"' Bus "+str(busline)+ u": "+destination) return True elif direction == "DIR_OUTWARD": # positive list: for (itemid, itemdest) in outwardlist: if destination == itemdest: # the destination is in the list if itemid == 0 or itemid == busline: # the destination matches for all buses or the bus is the right one myask_log.debug(10, u"Match: Found outbound match for station '"+key+u"' Bus "+str(busline)+ u": "+destination) return True # negative list let's check if the item is in the outbound list for (itemid, itemdest) in inwardlist: if destination == itemdest: # the destination is in the list if itemid == 0 or itemid == busline: # the destination matches for all buses or the bus is the right one myask_log.debug(10, u"Mismatch: Found inbound match for station '"+key+u"' Bus "+str(busline)+ u": "+destination) return False myask_log.debug(10, u"Did not find in/out match for '"+key+u"' Bus "+str(busline)+ ": "+destination) return True else: myask_log.error(u"Invalid direction '"+str(direction) +u"' found ignoring filter") return True
def GetConnections(origin_ID, destination_ID, utc_offset): #--------------------------------------------------------------------------- # Retrieves a connection from the ASEAG server (using get_routedata) and # returns the connection in a simplified format # PARAMETERS: # - origin_ID: Bus stop ID for the departure station (integer, 1000000-999999) # - destination_ID: Bus stop ID for the departure station (integer, 1000000-999999) # - utc_offset: Timezone, for which the times should be returned (API uses UTC) # # RETURNS: datastructure holding multiple connections (joruneys) # Each connection can consist of several parts ('legs') # '[ // list of journeys (matching connections) # 'start_datetime' : (datetime) departure time in local time # 'end_datetime' : (datetime) arrival time in local time # 'start_loc' : (string) name of the overall departure station # 'end_loc' : (string) name of the overall arrival station # 'legs' : [ // list of legs in this journey # 'type' : 'LineChange' | 'bus' | 'walk' # 'start_loc': (string) name of the departure location for this leg # 'end_loc' : (string) name of the arrival location for this leg # 'line' (string) name of busline (only for type 'bus') # 'start_datetime' : (datetime) start time for this leg (in local time) # 'end_datetime' : (datetime) end time for this leg (in local time) # ] # ] # If an error occurs, the function returns an empty connection list # If an error occurs parsing a specific journey, this journey is returned as empty #--------------------------------------------------------------------------- myask_log.debug(3, u"Fetching connection from '"+str(origin_ID) + u"' to '"+ str(destination_ID)+u"'...") output = get_routedata(origin_ID, destination_ID) if output == None: return [] # print "CONNECTION:-------------------------" # print json.dumps(output, indent=4, sort_keys=False) # print "END_CONNECTION-------------------------------------" result_connections = [] for journey in output['resultList']: res_journey = {} try: # get jorney_start end end time res_journey['start_datetime'] = unix_epoch_to_utcdatetime(journey['startTimeInUnixEpochMillis']) + datetime.timedelta(hours = utc_offset) res_journey['end_datetime'] = unix_epoch_to_utcdatetime(journey['endTimeInUnixEpochMillis']) + datetime.timedelta(hours = utc_offset) res_journey['start_loc'] = journey['startLocation']['stopPointName'] res_journey['end_loc'] = journey['endLocation']['stopPointName'] res_journey['legs'] = [] #loop over all parts (legs) of this journey for connection_leg in journey['elementList']: res_connection_leg = {} if connection_leg["type"] == "LineChange": res_connection_leg ['type'] = "LineChange" elif connection_leg['modalType'] == "bus": res_connection_leg['type'] = "bus" res_connection_leg['start_loc'] = connection_leg['start']['location']['stopPointName'] res_connection_leg['end_loc'] = connection_leg['end']['location']['stopPointName'] res_connection_leg['line'] = connection_leg['lineName'] tmp_datetime = unix_epoch_to_utcdatetime( connection_leg['start']['aimedArrivalInUnixEpochMillis'] or connection_leg['start']['estimatedArrivalInUnixEpochMillis'] or connection_leg['start']['scheduledArrivalInUnixEpochMillis']) res_connection_leg['start_datetime'] = tmp_datetime + datetime.timedelta(hours = utc_offset) tmp_datetime = unix_epoch_to_utcdatetime( connection_leg['end']['aimedArrivalInUnixEpochMillis'] or connection_leg['end']['estimatedArrivalInUnixEpochMillis'] or connection_leg['end']['scheduledArrivalInUnixEpochMillis']) res_connection_leg['end_datetime'] = tmp_datetime + datetime.timedelta(hours = utc_offset) elif connection_leg['modalType'] == "walk": res_connection_leg ['type'] = "walk" tmp_datetime = unix_epoch_to_utcdatetime( connection_leg['start']['aimedArrivalInUnixEpochMillis'] or connection_leg['start']['estimatedArrivalInUnixEpochMillis'] or connection_leg['start']['scheduledArrivalInUnixEpochMillis']) res_connection_leg['start_datetime'] = tmp_datetime + datetime.timedelta(hours = utc_offset) tmp_datetime = unix_epoch_to_utcdatetime( connection_leg['end']['aimedArrivalInUnixEpochMillis'] or connection_leg['end']['estimatedArrivalInUnixEpochMillis'] or connection_leg['end']['scheduledArrivalInUnixEpochMillis']) res_connection_leg['end_datetime'] = tmp_datetime + datetime.timedelta(hours = utc_offset) res_connection_leg['start_loc'] = connection_leg['start']['location']['stopPointName'] res_connection_leg['end_loc'] = connection_leg['end']['location']['stopPointName'] res_journey['legs'].append(res_connection_leg) except KeyError as e: myask_log.error(u"error: cannot parse journey "+ str(journey)) print e.message, e.args # print json.dumps(output, indent=4, sort_keys=False) res_journey = [] result_connections.append(res_journey) myask_log.debug(3, u"..."+str(len(result_connections))+u" connections found" ) return result_connections
def CollectInbound(outputfile): existing_connections = aseag_inbound_connection.INBOUND_LINES fout = open(outputfile, 'w+') fout.write("# coding: utf-8\n\n") fout.write("#List of inbound connections per station.\n") fout.write("#Auto-generated on " + datetime.now().strftime("%Y-%m-%d %H:%M") + "\n\n") fout.write("INBOUND_LINES= {\n") newcounter = 0 existingcounter = 0 observedcounter = 0 stationcounter = 0 nodirect_con = 0 for station in aseag_data.STATIONLIST: stationcounter += 1 origin_id = int(station[0]) orig_str = str(origin_id) myask_log.debug(9, "--- Station: " + orig_str) if orig_str in existing_connections: debugstr = "--- Station: " + orig_str inbound_line_departures = existing_connections[orig_str] # do some statistics stationlinecounter = 0 for lines in inbound_line_departures: stationlinecounter += len(lines) existingcounter += stationlinecounter else: debugstr = "+++ Station: " + orig_str inbound_line_departures = {} dircon = aseag_api.getDirectConnection(origin_id, 100000) if len(dircon ) == 0: # no direct connection to bushof, let's try kaiserplatz dircon = aseag_api.getDirectConnection(origin_id, 100003) if len(dircon) > 0: debugstr += "(KP):" else: debugstr += " NONE" else: debugstr += " :" # dircon = [] for con in dircon: observedcounter += 1 dest = con['destinationName'] # if dest == "Aachen Bushof" : continue line = con['lineName'] if line not in inbound_line_departures: debugstr += "+" myask_log.debug(3, "new: " + str(line) + " --> " + dest) newcounter += 1 stationlinecounter += 1 inbound_line_departures[line] = [dest] else: if dest not in inbound_line_departures[line]: debugstr += "+" myask_log.debug(3, "new: " + str(line) + " --> " + dest) newcounter += 1 stationlinecounter += 1 inbound_line_departures[line].append(dest) else: debugstr += "." myask_log.debug(9, "old " + str(line) + " --> " + dest) myask_log.debug(3, str(stationcounter) + " : " + debugstr) data_str = json.dumps(inbound_line_departures, sort_keys=True, ensure_ascii=False, separators=(',', ':')).encode('utf8') #enforce proper unicode tracking to avoid issues when re-reading data_str = data_str.replace('["', '[u"') data_str = data_str.replace('","', '", u"') fout.write(" '" + str(origin_id) + "' : " + data_str + ",\n") # do some statistics if stationlinecounter == 0: nodirect_con += 1 fout.write("}") fout.close() myask_log.debug(1, "-----------------------------------") myask_log.debug( 1, "Stations: " + str(stationcounter) + " (" + str(nodirect_con) + " without direction info)") myask_log.debug(1, "Existing: Dest. " + str(existingcounter) + " ") myask_log.debug( 1, "Observed Dest. " + str(observedcounter) + " destinations found this time") myask_log.debug( 1, "New Destinations " + str(newcounter) + " destinations added")