示例#1
0
    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)
示例#2
0
    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)
示例#3
0
    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