def add_report_to_tracker(tracker_id, report): logger.info('Adding report to tracker_id "{}": {}'.format(tracker_id, report)) day = set_tracker_day(tracker_id, report) # update train position if report.get_my_loc(): update_coords(report, tracker_id) is_updated_stop_time = stop_detector.add_report(tracker_id, report) if is_updated_stop_time: logger.info('stop_time updated') stop_times = stop_detector.get_detected_stop_times(tracker_id) trip_delays_ids_list_of_lists = update_trips(tracker_id, day, stop_times) trip_ids = get_trusted_trips(trip_delays_ids_list_of_lists) for trip_id in trip_ids: trip_delays_ids_list = [x for x in trip_delays_ids_list_of_lists if x[0][1] == trip_id][0] if (len(stop_times)-1) in trip_delays_ids_list[0][2]: if len(trip_delays_ids_list[0][2]) == 2: # Need to add the first station if (len(stop_times)-2) in trip_delays_ids_list[0][2]: stop_time = stop_times[trip_delays_ids_list[0][2][-2]] logger.debug(stop_time) save_stop_times_to_db(tracker_id, stop_time, trip_id) else: logger.error('Two stops were detected for trip, last detected stop for tracker belongs to trip, but one before last does not, while it most probably should.') stop_time = stop_times[trip_delays_ids_list[0][2][-1]] logger.debug(stop_time) save_stop_times_to_db(tracker_id, stop_time, trip_id)
def get_trusted_trips(trip_delays_ids_list_of_lists): trip_ids = [] if not trip_delays_ids_list_of_lists: return trip_ids for trip_delays_ids_list in trip_delays_ids_list_of_lists: trips = [x[1] for x in trip_delays_ids_list] time_deviation_in_seconds = [x[0] for x in trip_delays_ids_list] trip_id = get_trusted_trip_or_none(trips, time_deviation_in_seconds) if trip_id: trip_ids.append(trip_id) logger.info('Trusted trips={} for trip_delays_ids_list_of_lists={}'.format(trip_ids, trip_delays_ids_list_of_lists)) return trip_ids
def get_trusted_trip_or_none(trips, time_deviation_in_seconds): # some heuristics to evaluate if we already have a trip we trust # enough to save it in db: if not trips: return None if len(time_deviation_in_seconds) > 1: time_deviation_ratio = time_deviation_in_seconds[0]/time_deviation_in_seconds[1] else: time_deviation_ratio = 0; do_trust_trip = len(trips) > 0 and time_deviation_ratio < 0.5 if do_trust_trip: logger.info('time_deviation_ratio={} and so we trust trip={}'.format(time_deviation_ratio, trips[0])) return trips[0] else: logger.info('time_deviation_ratio={} and so we do not trust trip={}'.format(time_deviation_ratio, trips[0])) return None
def update_coords(report, tracker_id): loc = report.get_my_loc() coords = [loc.lat, loc.lon] logger.info('Updating coords for tracker_id={} by report={} to coords={}'.format(tracker_id, report, coords)) res_shape_sampled_point_ids, _ = shapes.all_shapes.query_sampled_points(coords, loc.accuracy_in_coords) added_count = cl.sadd(get_train_tracker_visited_shape_sampled_point_ids_key(tracker_id), res_shape_sampled_point_ids) trip_delays_ids_list_of_lists = load_by_key(get_train_tracker_trip_delays_ids_list_of_lists_key(tracker_id)) trips = get_trusted_trips(trip_delays_ids_list_of_lists) for trip in trips: cl.setex(get_current_trip_id_report_timestamp_key(trip), TRACKER_TTL, ot_utils.dt_time_to_unix_time(report.timestamp)) if added_count > 0: save_by_key(get_current_trip_id_coords_key(trip),\ coords,\ timeout=TRACKER_TTL, cl=p) save_by_key(get_current_trip_id_coords_timestamp_key(trip),\ ot_utils.dt_time_to_unix_time(report.timestamp),\ timeout=TRACKER_TTL, cl=p) else: # extend expiration: p.expire(get_current_trip_id_coords_key(trip), TRACKER_TTL) p.expire(get_current_trip_id_coords_timestamp_key(trip), TRACKER_TTL) p.execute()
def save_stop_times_to_db(tracker_id, detected_stop_time, trip_id): logger.info('Saving stop_time to db. trip_id={}, stop_time={}'.format(trip_id, detected_stop_time)) stop = timetable.services.get_stop(detected_stop_time.stop_id) departure_time = detected_stop_time.departure arrival_time = detected_stop_time.arrival from analysis.models import RtStop try: rs = RtStop.objects.get(tracker_id=tracker_id,stop=stop,trip__gtfs_trip_id=trip_id) logger.info('RtStop exists. Overriding.') except RtStop.DoesNotExist: rs = RtStop() logger.info('RtStop does not exist. Creating new one.') rs.tracker_id = tracker_id rs.trip = timetable.services.get_trip(trip_id) rs.stop = stop rs.act_arrival = arrival_time rs.act_departure = departure_time rs.save() logger.info('RtStop saved: {}'.format(rs))
def set_current(self, state, stop_id, timestamp): key = get_train_tracker_data_key( self.tracker_id) value = (state, str(stop_id), timestamp.isoformat()) logger.info('key={}, value={}'.format(key, value)) save_by_key(key, value, cl=p)
def __init__(self, tracker_id): logger.info('init detector_state') self.tracker_id = tracker_id
def _try_add_report(tracker_id, report): logger.info('tracker_id={} report={}'.format(tracker_id, report)) is_updated_stop_time = False logger.info('fetching detector_state.') detector_state = DetectorState(tracker_id) logger.info('fetched detector_state.') prev_state, prev_stop_id, prev_timestamp = detector_state.get_current() logger.info('prev_state={} prev_stop_id={} prev_timestamp={}'.format(prev_state, prev_stop_id, prev_timestamp)) # new report is older than last report: if prev_timestamp and report.timestamp < prev_timestamp: logger.warning('New report is older than last report. New report timestamp={}. Last report timestamp={}'.format(report.timestamp, prev_timestamp)) return is_updated_stop_time state, stop_id, timestamp = _get_report_data(report) logger.info('state={} stop_id={} timestamp={}'.format(state, stop_id, timestamp)) if prev_timestamp and timestamp - prev_timestamp > config.no_report_timegap: detector_state_transition = DetectorState.transitions.NOREPORT_TIMEGAP else: detector_state_transition = DetectorState.transitions.NORMAL logger.info('Setting detector state: state={} stop_id={} timestamp={}'.format(state, stop_id, timestamp)) detector_state.set_current(state, stop_id, timestamp) if prev_state in [DetectorState.states.INITIAL, DetectorState.states.NOSTOP]: if state == DetectorState.states.NOSTOP: logger.info('passing big if statement') pass elif state == DetectorState.states.STOP: _start_stop_time(tracker_id, stop_id, timestamp) is_updated_stop_time = True elif state == DetectorState.states.UNKNOWN_STOP: # TODO: Add handling of UNKNOWN_STOP stop_time logger.info('passing big if statement') pass elif prev_state == DetectorState.states.STOP: if state == DetectorState.states.NOSTOP: stop_time = get_last_detected_stop_time(tracker_id) _end_stop_time( tracker_id, prev_stop_id, stop_time.arrival, prev_timestamp, stop_time) is_updated_stop_time = True elif state == DetectorState.states.STOP: if detector_state_transition == DetectorState.transitions.NOREPORT_TIMEGAP: stop_time = get_last_detected_stop_time(tracker_id) print 'NOREPORT_TIMEGAP' _end_stop_time(tracker_id, prev_stop_id, stop_time.arrival, prev_timestamp, stop_time) _start_stop_time(tracker_id, prev_stop_id, timestamp, stop_time, True) is_updated_stop_time = True elif prev_stop_id != stop_id: stop_time = get_last_detected_stop_time(tracker_id) _end_stop_time(tracker_id, prev_stop_id, stop_time.arrival, prev_timestamp, stop_time) _start_stop_time(tracker_id, stop_id, timestamp, stop_time) is_updated_stop_time = True elif state == DetectorState.states.UNKNOWN_STOP: # TODO: Add handling of UNKNOWN_STOP stop_time logger.info('passing big if statement') pass elif prev_state == DetectorState.states.UNKNOWN_STOP: if state == DetectorState.states.NOSTOP: # TODO: Add handling of UNKNOWN_STOP stop_time logger.info('passing big if statement') pass elif state == DetectorState.states.STOP: # TODO: Add handling of UNKNOWN_STOP stop_time logger.info('passing big if statement') pass elif state == DetectorState.states.UNKNOWN_STOP: # TODO: Add handling of UNKNOWN_STOP stop_time logger.info('passing big if statement') pass return is_updated_stop_time
def add_report(tracker_id, report): logger.info('adding report={}'.format(report)) is_updated_stop_time = False report_id = cl.incr(get_train_tracker_report_id_key(tracker_id)) updated_report_id_key = get_train_tracker_updated_report_id_key( tracker_id) # We try to update a report only if no report was updated with a more recent # report_id than us. If one was updated, we don't update at all. # This is done using check-and-set (see http://redis.io/topics/transactions) done = False while not done: logger.info('watching {}'.format(updated_report_id_key)) p.watch(updated_report_id_key) updated_report_id = load_by_key(updated_report_id_key, logger=logger) logger.info('updated_report_id={}, report_id={}'.format(updated_report_id, report_id)) if not updated_report_id or updated_report_id < report_id: try: p.multi() is_updated_stop_time = _try_add_report(tracker_id, report) p.set(updated_report_id_key, report_id) p.execute() done = True except WatchError: logger.info('WatchError: {}'.format(WatchError)) done = False p.unwatch() else: logger.info('Report not used because of report_id.') done = True p.unwatch() logger.info('is_updated_stop_time={}, done={}'.format(is_updated_stop_time, done)) return is_updated_stop_time and done
def _end_stop_time(tracker_id, stop_id, arrival_time, departure_time, prev_stop_time=None): logger.info('Calling _end_stop_time.') _update_stop_time(tracker_id, arrival_time, stop_id, departure_time, prev_stop_time)
def _start_stop_time(tracker_id, stop_id, arrival_time, prev_stop_time=None, is_report_timegap=False): logger.info('Calling _start_stop_time. is_report_timegap={}'.format(is_report_timegap)) _update_stop_time(tracker_id, arrival_time, stop_id, None, prev_stop_time, is_report_timegap)
def update_trips(tracker_id, day, detected_stop_times): logger.info('Updating trips for tracker_id={}'.format(tracker_id)) trip_delays_ids_list_of_lists = trip_matcher.get_matched_trips(tracker_id, detected_stop_times, day) logger.info('Updated trip_delays_ids_list_of_lists for tracker_id={}: {}'.format(tracker_id, trip_delays_ids_list_of_lists)) save_by_key(get_train_tracker_trip_delays_ids_list_of_lists_key(tracker_id), trip_delays_ids_list_of_lists) return trip_delays_ids_list_of_lists