def DisplayJourneySimple(journey, slots, appdef): if 'legs' not in journey or len(journey['legs']) == 0: display_text = "ERROR_IN_CONNECION" myask_log.error("DisplayJourneySimple: cannot present connection: " + str(journey)) else: display_text = u'{:5s} ab {:15s} --> {:15s} an {:5s} {:d} Umstiege '.format( journey['start_datetime'].strftime('%H:%M'), unicode(journey['start_loc']), unicode(journey['end_loc']), journey['end_datetime'].strftime('%H:%M'), len(journey['legs']) - 1) display_text += "(" firstleg = True for leg in journey['legs']: if firstleg: firstleg = False else: display_text += ", " if leg['type'] == "bus": if 'line' in leg: display_text += "Bus " + leg['line'] else: display_text += "Bus ??" elif leg['type'] == "walk": display_text += "laufen" display_text += ")\n" return display_text
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 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_inbound_connection.INBOUND_LINES: inwardlist = aseag_inbound_connection.INBOUND_LINES[key] else: myask_log.error("Station '" + str(station_ID) + "' not found in inbound list. returning all stations") return True if direction == "DIR_INWARD": # positive list: if destination in aseag_data.CENTRAL_DESTINATIONS: # if bus goes to one of those, it is by definition inbound. no need to look further return True elif str( line ) in inwardlist: # we have a list of destinations of that line, which pass through the center if destination in inwardlist[str(line)]: return True else: return False else: #line unknown return False elif direction == "DIR_OUTWARD": # exclude all known inbound lines if destination in aseag_data.CENTRAL_DESTINATIONS: # if bus goes to one of those, it is by definition inbound. no need to look further return False elif str( line ) in inwardlist: # we have a list of destinations of that line, which pass through the center if destination in inwardlist[str(line)]: return False else: return True else: #line unknown return True else: myask_log.error(u"Invalid direction '" + str(direction) + u"' found ignoring filter") return True
def get_user_profile(session): #get the user id from the request if session['user']['userId'] == "": myask_log.error( "Missing field 'session.user.userId'. Assuming default user") user_profile = bus_userprofile.userProfile( "") # create default_profile else: user_profile = bus_userprofile.userProfile(session['user']['userId']) return user_profile
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 SpeakConnection(journey, slots, appdef): speech_output = "" if 'legs' not in journey or len(journey['legs']) == 0: speech_output += u"Diese Verbindung kann ich noch nicht vorlesen.<break/>" myask_log.error("DisplayJourneySimple: cannot present connection: " + str(journey)) elif len(journey['legs']) == 1: #direct connection leg = journey['legs'][0] if leg['type'] == "bus": if 'line' in leg: speech_output += u"Mit der Linie " + leg['line'] else: speech_output += u"Mit dem Bus" speech_output += u" <break/> " speech_output += u" Abfahrt " + journey['start_loc'] speech_output += u" um " + journey['start_datetime'].strftime( '%H:%M') + " . " speech_output += u" Ankunft " + journey['end_loc'] speech_output += u" um " + journey['end_datetime'].strftime( '%H:%M') + " . " else: # multi-leg trip speech_output += u"Mit " firstleg = True for leg in journey['legs']: if firstleg: firstleg = False else: speech_output += u" und " if leg['type'] == u"bus": if 'line' in leg: speech_output += u"Bus " + leg['line'] else: speech_output += u"Bus" elif leg['type'] == "walk": speech_output += u"Fussweg" speech_output += u" <break/>" speech_output += u" Abfahrt " + journey['start_loc'] speech_output += u" um " + journey['start_datetime'].strftime( '%H:%M') + " . " speech_output += u" Ankunft " + journey['end_loc'] speech_output += u" um " + journey['end_datetime'].strftime( '%H:%M') + " . " speech_output += u"<break/>" return speech_output
def get_stopdata(stop_point_id, lines, getraw=False): #-------------------------------------------------------------------------- # returns the next buses of given lines from a bus stop # parameter = {'ReturnList': returnlist, 'StopID': stop_point_id} if lines: parameter['LineID'] = ",".join(lines) request = requests.get(baseurl.format(url_i), params=parameter) if request.status_code != 200: myask_log.error("ASEAG API returned error code" + str(request.status_code)) return [] if request.headers['content-type'] != 'application/json;charset=UTF-8': myask_log.error("ASEAG API returned invalid result") return [] if getraw: return request.text else: data = deduplication(parsejson(request.text, request.encoding)) return data
def get_routedata(origin_ID, destination_ID): #--------------------------------------------------------------------------- # core function for retrieving a connection from the ASEAG server # 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) # RETURNS: # raw JSON data structure with the connection results #--------------------------------------------------------------------------- parameter = { 'startStopId': origin_ID, 'endStopId': destination_ID, 'departureTime': unix_epoch_from_now(), 'maxNumResults': 4 } request = requests.get(baseurl.format(url_j), params=parameter) if request.status_code != 200: myask_log.error(u"ASEAG API call returned unexpected status code '" + str(request.status_code) + u"' \nRequest: " + str(request)) return None if 'content-type' not in request.headers: myask_log.error(u"ASEAG API call misses header '" + str(request.headers) + u"' \nRequest: " + str(request)) return None if request.headers['content-type'] != 'application/json;charset=UTF-8': myask_log.error(u"ASEAG API call returned unexpected header '" + str(request.headers['content-type']) + u"' \nRequest: " + str(request)) return None data = request.json() return data
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 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 main(): # - aseag_api.py [-oid DEP_STOP_ID] [-did DESTINATION_STOP_ID] [-line LINENUMBER] [-dir IN_OUT] [-t TRANSPORT] [-raw] # - if no origin is given, system uses default-stop # - if no destination is given, system shows departures from origin # output: if '-raw' is given, present raw output from ASEAG API, else give simplified output print("in main") parser = argparse.ArgumentParser() parser.add_argument("-v", "--verbosity", type=int, help="define output verbosity") org_group = parser.add_mutually_exclusive_group(required=True) org_group.add_argument( "-oid", "--origin_id", type=int, help="6-digit station ID of origin (departure) station") org_group.add_argument("-oname", "--origin_name", type=str, help="name of origin (departure) station") dep_group = parser.add_mutually_exclusive_group() dep_group.add_argument("-did", "--destination_id", type=int, help="6-digit station ID of destination station") dep_group.add_argument("-dname", "--destination_name", type=str, help="name of destination station") parser.add_argument("-l", "--busline", type=str, help="Line (NR or string") parser.add_argument("-dir", "--direction", type=int, help="direction: 1=inward 2=outward") parser.add_argument("-raw", "--raw_mode", action="store_true", help="If set, output raw API results") args = parser.parse_args() if args.verbosity: myask_log.SetDebugLevel(args.verbosity) if args.origin_id: origin_id = args.origin_id elif args.origin_name: origin_id_list = get_stoppoint(args.origin_name) if len(origin_id_list) != 1: myask_log.error("no unique stop found") for alt in origin_id_list: print alt return else: origin_id = origin_id_list[0][0] else: myask_log.error("origin destination not specified") origin_id = int(origin_id) # just to be sure if origin_id < 100000 or origin_id > 999999: myask_log.error("invalid origin id '" + str(origin_id) + "#") if args.destination_id: destination_id = args.destination_id elif args.destination_name: destination_id_list = get_stoppoint(args.destination_name) if len(destination_id_list) != 1: myask_log.error("no unique stop found") for alt in destination_id_list: print alt return else: destination_id = destination_id_list[0][0] else: destination_id = 0 # code for not set destination_id = int(destination_id) # just to be sure if destination_id != 0 and (destination_id < 100000 or destination_id > 999999): myask_log.error("invalid destination_id '" + str(destination_id) + "#") return if args.busline: busline = args.busline else: busline = "" if args.direction: if args.direction == 1: direction = "DIR_INWARD" elif args.direction == 2: direction = "DIR_OUTWARD" else: myask_log.error("invalid direction '" + str(args.direction) + " (must be 1 (inbound) or 2 (outbound)") return else: direction = "" # now process the commands if destination_id == 0: # (departures only) if args.raw_mode: if direction != "": print "Departure Post-Filter for direction not supported in raw mode" if busline == "": buslines = [] else: buslines = [busline] results = get_stopdata(origin_id, buslines, getraw=True) print results else: results = GetDepartures(origin_id, busline, direction, utc_offset=1) for result in results: print result else: # origin and destination if args.raw_mode: if busline != "": print "Connection Post-Filter for busline not supported in raw mode" print "Raw results-----------------" output = get_routedata(origin_id, destination_id) print json.dumps(output, indent=4, sort_keys=False) else: match, results = GetConnectionsWithBus(origin_id, destination_id, busline, utc_offset=1) print "Match: " + str(match) for result in results: print result