def handle_stop(self, pvt): """Handle the stop point. """ flag = self.check_timestamp(int(pvt['gps_time'])) if not flag: return tid = pvt['dev_id'] stop_key = get_stop_key(tid) stop = self.redis.getvalue(stop_key) distance_key = get_distance_key(tid) distance = self.redis.get(distance_key) if not distance: distance = 0 last_pvt_key = get_last_pvt_key(tid) last_pvt = self.redis.getvalue(last_pvt_key) if last_pvt: distance = float(distance) + lbmphelper.get_distance(int(last_pvt["lon"]), int(last_pvt["lat"]), int(pvt["lon"]), int(pvt["lat"])) self.redis.setvalue(distance_key, distance, time=EVENTER.STOP_EXPIRY) if pvt['speed'] > LIMIT.SPEED_LIMIT: # is moving if stop: #NOTE: time_diff is too short, drop the point. if pvt["gps_time"] - stop['start_time'] < 60: # 60 seconds _stop = self.db.get("SELECT distance FROM T_STOP WHERE lid =%s", stop['lid']) if _stop: tmp_dis = _stop['distance'] else: tmp_dis = 0 distance = float(distance) + tmp_dis self.db.execute("DELETE FROM T_STOP WHERE lid = %s", stop['lid']) self.redis.delete(stop_key) self.redis.setvalue(distance_key, distance, time=EVENTER.STOP_EXPIRY) logging.info("[EVENTER] Stop point is droped: %s", stop) else: # close a stop point self.redis.delete(stop_key) self.db.execute("UPDATE T_STOP SET end_time = %s WHERE lid = %s", pvt["gps_time"], stop['lid']) logging.info("[EVENTER] Stop point is closed: %s", stop) else: pass else: # low speed, may stop if stop: logging.info("[EVENTER] Stop point is updated: %s", stop) stop['end_time'] = pvt["gps_time"] self.redis.setvalue(stop_key, stop, time=EVENTER.STOP_EXPIRY) logging.info("[EVENTER] Stop point is updated: %s", stop) else: # create a new stop point pvt = lbmphelper.handle_location(pvt, self.redis, cellid=True, db=self.db) lid = insert_location(pvt, self.db, self.redis) stop = dict(lid=lid, tid=tid, start_time=pvt["gps_time"], end_time=0, pre_lon=pvt["lon"], pre_lat=pvt["lat"], distance=distance) self.db.execute("INSERT INTO T_STOP(lid, tid, start_time, distance) VALUES(%s, %s, %s, %s)", lid, tid, pvt["gps_time"], distance) self.redis.setvalue(stop_key, stop, time=EVENTER.STOP_EXPIRY) self.redis.delete(distance_key) logging.info("[EVENTER] Stop point is created: %s", stop)
def handle_position_info(self, location): """Handle the info of position, include PVT(T11), CALL(T3) """ location = DotDict(location) current_time = int(time.time()) #NOTE: Now, it is seldom appears if location.Tid == EVENTER.TRIGGERID.CALL: if location['gps_time'] > (current_time + 24*60*60): logging.info("[EVENTER] The location's (gps_time - current_time) is more than 24 hours, so drop it:%s", location) return location = lbmphelper.handle_location(location, self.redis, cellid=True, db=self.db) ## check regions #for region in regions: # region_location = self.check_region_event(location, region) # if region_location and region_location['t'] == EVENTER.INFO_TYPE.REPORT: # self.handle_report_info(region_location) location['category'] = EVENTER.CATEGORY.REALTIME update_terminal_dynamic_info(self.db, self.redis, location) if location.get('lat') and location.get('lon'): self.realtime_location_hook(location) # NOTE: For pvt(T11) elif location.Tid == EVENTER.TRIGGERID.PVT: #NOTE: get speed_limit # make pvts sortd according gsp_time pvts = sorted(location['pvts'], key=lambda x:x['gps_time']) for pvt in pvts: #for pvt in location['pvts']: # The 'future time' is drop if pvt['gps_time'] > (current_time + 24*60*60): logging.info("[EVENTER] The location's (gps_time - current_time) is more than 24 hours, so drop it:%s", pvt) continue # get available location from lbmphelper pvt['dev_id'] = location['dev_id'] pvt['Tid'] = location['Tid'] pvt['valid'] = GATEWAY.LOCATION_STATUS.SUCCESS pvt['type'] = 0 #NOTE: handle stop self.handle_stop(pvt) #NOTE: handle region self.handle_region(pvt) #NOTE: handle single self.handle_single(pvt) #NOTE: handle speed self.handle_speed(pvt) #NOTE: the time of keep last_pvt is import. First check single, then keep pvt last_pvt_key = get_last_pvt_key(location['dev_id']) last_pvt = pvt self.redis.setvalue(last_pvt_key, last_pvt, time=EVENTER.STOP_EXPIRY) # NOTE: not offset it #location = lbmphelper.handle_location(pvt, self.redis, # cellid=False, db=self.db) #NOTE: mileage pvt['category'] = EVENTER.CATEGORY.REALTIME if pvt.get('lat') and pvt.get('lon'): insert_location(pvt, self.db, self.redis) #NOTE: handle mileage self.handle_mileage(pvt) self.push_to_client(pvt) else: location.category = EVENTER.CATEGORY.UNKNOWN self.unknown_location_hook(location)
def check_single_event(self, ori_location, single): """Check enter or out single workflow: get old_single_status accordinding to single and tid get old_single_time accordinding to single and tid check single_status according distance, then keep single_status in redis if not old_single_status: skip if old_single_time and location's gps_time <= old_region_time: skip check single event according to single_status and old_single_staus if single event: keep single_status, single_time in redis """ if not (ori_location and single): logging.info("[EVENTER] query data is invalid, ori_location: %s, single: %s, do not check.", ori_location, single) return None if not (ori_location['cLat'] and ori_location['cLon']): logging.info("[EVENTER] location is invalid, ori_location: %s, do not check.", ori_location) return None # BIG NOTE: python grammar, shallow copy will change origen data. location = copy.deepcopy(dict(ori_location)) location = DotDict(location) old_single_status_key = get_single_status_key(location['dev_id'], single.single_id) old_single_status = self.redis.getvalue(old_single_status_key) old_single_time_key = get_single_time_key(location['dev_id'], single.single_id) old_single_time = self.redis.getvalue(old_single_time_key) if single.single_shape == UWEB.SINGLE_SHAPE.CIRCLE: # get distance beteween now location and the centre of the region distance = lbmphelper.get_distance(single.single_longitude, single.single_latitude, location.cLon, location.cLat) if distance >= single.single_radius: single_status = EVENTER.CATEGORY.SINGLE_OUT rname = EVENTER.RNAME.SINGLE_OUT else: single_status = EVENTER.CATEGORY.SINGLE_ENTER rname = EVENTER.RNAME.SINGLE_ENTER elif single.single_shape == UWEB.SINGLE_SHAPE.POLYGON: polygon = {'name':'', 'points':[]} points = single.points point_lst = points.split(':') for point in point_lst: latlon = point.split(',') dct = {'lat':float(latlon[0])/3600000, 'lon':float(latlon[1])/3600000} polygon['points'].append(dct) polygon['name'] = single.single_name if PtInPolygon(location, polygon): single_status = EVENTER.CATEGORY.SINGLE_ENTER rname = EVENTER.RNAME.SINGLE_ENTER else: single_status = EVENTER.CATEGORY.SINGLE_OUT rname = EVENTER.RNAME.SINGLE_OUT else: #NOTE: here should never occur. logging.error("[EVENTER] unknow single_shape: %s, single: %s, skip it", single.single_shape, single) #NOTE: skip the time if old_single_time: if int(location['gps_time']) <= int(old_single_time): logging.info("[EVENTER] current location's gps_time: %s is not bigger than old_single_time: %s, skip it", location['gps_time'], old_single_time) return location logging.info('old_single_status_key: %s, single_status: %s', old_single_status_key, single_status) # keep region status self.redis.setvalue(old_single_status_key, single_status) logging.info("rname:%s, old status:%s, current status:%s, tid:%s", safe_unicode(single.single_name), old_single_status, single_status, location['dev_id']) if not old_single_status: logging.info("[EVENTER] old_single_status: %s is invalid, skip it", old_single_status) # skip the first region event return location # check single event if single_status != old_single_status: self.redis.setvalue(old_single_status_key, single_status) self.redis.setvalue(old_single_time_key, location['gps_time']) # 2: complete the location location['category'] = single_status location['t'] = EVENTER.INFO_TYPE.REPORT #NOTE: t is need location['rName'] = rname location['single'] = single location['single_id'] = single.single_id # 3. keep it in db # out first, then enter if single_status == EVENTER.CATEGORY.SINGLE_ENTER: single_event = self.db.get("SELECT id as seid, tid, sid, start_time, end_time" " FROM T_SINGLE_EVENT" " WHERE tid = %s " " AND sid = %s" " AND start_time !=0" " AND end_time = 0 " " ORDER BY id DESC LIMIT 1", location['dev_id'], location['single_id']) if not single_event: pass else: self.db.execute("UPDATE T_SINGLE_EVENT" " SET end_time = %s" " WHERE id = %s", location['gps_time'], single_event['seid']) elif single_status == EVENTER.CATEGORY.SINGLE_OUT: last_pvt_key = get_last_pvt_key(location['dev_id']) last_pvt = self.redis.getvalue(last_pvt_key) if last_pvt: gps_time = last_pvt['gps_time'] else: gps_time = location['gps_time'] self.db.execute("INSERT INTO T_SINGLE_EVENT(tid, sid, start_time)" " VALUES(%s, %s, %s)", location['dev_id'], location['single_id'], gps_time) return location