def get_track_distance(self, track): """Get distance of a section of track. """ distance = 0 if not track: pass else: start_point = None for point in track: if not start_point: start_point = point continue else: distance += get_distance(start_point["longitude"], start_point["latitude"], point["longitude"], point["latitude"]) start_point = point return distance
def block_test(): db = DBConnection().db redis = MyRedis() #start_time = int(time.mktime(time.strptime("%s-%s-%s-%s-%s-%s"%(2014,8,26,0,0,0),"%Y-%m-%d-%H-%M-%S"))) #end_time = int(time.mktime(time.strptime("%s-%s-%s-%s-%s-%s"%(2014,8,27,18,0,0),"%Y-%m-%d-%H-%M-%S"))) #print time.localtime(start_time) #print time.localtime(end_time) tid = '3922400068' start_time = 1409222189 end_time = 1409223445 track = db.query("SELECT id, latitude, longitude, clatitude," " clongitude, timestamp, name, type, speed, degree, locate_error" " FROM T_LOCATION" " WHERE tid = %s" " AND category = 1" " AND NOT (latitude = 0 OR longitude = 0)" " AND (timestamp BETWEEN %s AND %s)" " AND type = 0" " GROUP BY timestamp" " ORDER BY timestamp", tid, start_time, end_time) distance = 0 start_point = None for point in track: if not start_point: start_point = point continue else: distance += get_distance(start_point["longitude"], start_point["latitude"], point["longitude"], point["latitude"]) start_point = point print '---distance', distance, tid, start_time, end_time
def _on_finish(db): self.db = db if cellid_flag == 1: # gps track and cellid track track = self.db.query("SELECT id, latitude, longitude, clatitude," " clongitude, timestamp, name," " type, speed, degree, locate_error" " FROM T_LOCATION" " WHERE tid = %s" " AND NOT (latitude = 0 OR longitude = 0)" " AND (timestamp BETWEEN %s AND %s)" " GROUP BY timestamp" " ORDER BY timestamp", self.current_user.tid, start_time, end_time) else: # cellid_flag is None or 0, only gps track track = self.db.query("SELECT id, latitude, longitude, clatitude," " clongitude, timestamp, name, " " type, speed, degree, locate_error" " FROM T_LOCATION" " WHERE tid = %s" " AND NOT (latitude = 0 OR longitude = 0)" " AND (timestamp BETWEEN %s AND %s)" " AND type = 0" " GROUP BY timestamp" " ORDER BY timestamp", self.current_user.tid, start_time, end_time) # check track point count if track and len(track) > 500 and network_type == 0: logging.info("[UWEB] The %s track points length is: %s, " " and the newtork type is too low, so return error.", tid, len(track)) self.write_ret(ErrorCode.TRACK_POINTS_TOO_MUCH) self.finish() return # NOTE: if latlons are legal, but clatlons are illlegal, offset # them and update them in db. _start_time = time.time() track = get_locations_with_clatlon(track, self.db) _now_time = time.time() if _now_time - _start_time > 3: # 3 seconds logging.info("[UWEB] Track offset used time: %s s, tid: %s, cid: %s", _now_time - _start_time, self.current_user.tid, self.current_user.cid) # NOTE: filter point without valid clat and clon _track = [] for t in track: if t['clongitude'] and ['clatitude']: _track.append(t) else: logging.info("[UWEB] Invalid point: %s, drop it, cid: %s", t, self.current_user.cid) track = _track # add idle_points # track1, track2, track3,... # when the distance between two points is larger than 10 meters and the interval is less than 5 minutes, # they are regarded as idle_points idle_lst = [] idle_points = [] for i, item_start in enumerate(track): is_idle = False if i in idle_lst: continue for j in range(i + 1, len(track)): item_end = track[j] distance = get_distance( item_start.clongitude, item_start.clatitude, item_end.clongitude, item_end.clatitude) if distance >= UWEB.IDLE_DISTANCE: break else: idle_time = item_end[ 'timestamp'] - item_start['timestamp'] item_start['idle_time'] = idle_time item_start['start_time'] = item_start['timestamp'] item_start['end_time'] = item_end['timestamp'] idle_lst.append(j) is_idle = True if is_idle and item_start['idle_time'] > UWEB.IDLE_INTERVAL: idle_points.append(item_start) # modify name & degere for item in track: item['degree'] = float(item['degree']) if item.name is None: item['name'] = '' # organize and store the data to be downloaded m = hashlib.md5() m.update(self.request.body) hash_ = m.hexdigest() mem_key = self.KEY_TEMPLATE % (self.current_user.uid, hash_) res = [] if idle_lst: point_begin = dict(label=u'起点', start_time=utc_to_date( track[0]['timestamp']), end_time='', name=track[0]['name']) point_idle = [] for idle_point in idle_points: idle_label = seconds_to_label(idle_point['idle_time']) label = u'停留' + idle_label point = dict(label=label, start_time=utc_to_date( idle_point['start_time']), end_time=utc_to_date(idle_point['end_time']), name=idle_point['name']) point_idle.append(point) point_end = dict(label=u'终点', start_time=utc_to_date( track[-1]['timestamp']), end_time='', name=track[-1]['name']) res.append(point_begin) res.append(point_end) res.extend(point_idle) self.redis.setvalue(mem_key, res, time=UWEB.STATISTIC_INTERVAL) logging.info( "[UEB] Tid:%s track query, returned %s points.", self.current_user.tid, len(track)) self.write_ret(status, dict_=DotDict(track=track, idle_points=idle_points, hash_=hash_)) self.finish()
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_mileage(self, pvt): """Check the mileage. """ flag = self.check_timestamp(int(pvt['gps_time'])) if not flag: return #NOTE: record the mileage tid = pvt['dev_id'] mileage_key = get_mileage_key(tid) mileage = self.redis.getvalue(mileage_key) if not mileage: logging.info("[EVENTER] Tid: %s, init mileage. pvt: %s.", tid, pvt) mileage = dict(lat=pvt.get('lat'), lon=pvt.get('lon'), dis=0, gps_time=pvt['gps_time']) self.redis.setvalue(mileage_key, mileage) else: if pvt['gps_time'] < mileage['gps_time']: logging.info("[EVENTER] Tid: %s, gps_time: %s is less than mileage['gps_time']: %s, drop it. pvt: %s, mileage: %s", tid, pvt['gps_time'], mileage['gps_time'], pvt, mileage) pass else: dis = lbmphelper.get_distance(int(mileage["lon"]), int(mileage["lat"]), int(pvt["lon"]) , int(pvt["lat"])) # for mileage notification dis_current = mileage['dis'] + dis self.db.execute("UPDATE T_TERMINAL_INFO" " SET distance_current = %s" " WHERE tid = %s", dis_current, tid) logging.info("[EVENTER] Tid: %s, distance: %s. pvt: %s.", tid, dis_current, pvt) mileage = dict(lat=pvt.get('lat'), lon=pvt.get('lon'), dis=dis_current, gps_time=pvt['gps_time']) self.redis.setvalue(mileage_key, mileage) # for mileage junior statistic current_day = time.localtime(pvt['gps_time']) day_start_time, day_end_time = start_end_of_day(current_day.tm_year, current_day.tm_mon, current_day.tm_mday) mileage_log = self.db.get("SELECT * FROM T_MILEAGE_LOG" " WHERE tid = %s" " AND timestamp = %s", tid, day_end_time) if mileage_log: dis_day = mileage_log['distance'] + dis else: self.db.execute("INSERT INTO T_MILEAGE_LOG(tid, timestamp)" " VALUES(%s, %s)", tid, day_end_time) dis_day = dis self.db.execute("INSERT INTO T_MILEAGE_LOG(tid, distance, timestamp)" " VALUES(%s, %s, %s)" " ON DUPLICATE KEY" " UPDATE distance=values(distance)", tid, dis_day, day_end_time) logging.info("[EVENTER] Tid: %s, dis_day: %s. pvt: %s.", tid, dis_day, pvt)
def check_region_event(self, ori_location, region): """Check enter or out region workflow: get old_region_status accordinding to region and tid get old_region_time accordinding to region and tid check region_status according distance, then keep region_status in redis if not old_region_status: skip if old_region_time and location's gps_time <= old_region_time: skip check region event according to region_status and old_region_staus if region event: keep region_status, region_time in redis """ if not (ori_location and region): logging.info("[EVENTER] query data is invalid, ori_location: %s, region: %s, no check", ori_location, region) return None if not (ori_location['cLat'] and ori_location['cLon']): logging.info("[EVENTER] location is invalid, ori_location: %s, no 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_region_status_key = get_region_status_key(location['dev_id'], region.region_id) old_region_status = self.redis.getvalue(old_region_status_key) old_region_time_key = get_region_time_key(location['dev_id'], region.region_id) old_region_time = self.redis.getvalue(old_region_time_key) if region.region_shape == UWEB.REGION_SHAPE.CIRCLE: # get distance beteween now location and the centre of the region distance = lbmphelper.get_distance(region.region_longitude, region.region_latitude, location.cLon, location.cLat) if distance >= region.region_radius: region_status = EVENTER.CATEGORY.REGION_OUT rname = EVENTER.RNAME.REGION_OUT else: region_status = EVENTER.CATEGORY.REGION_ENTER rname = EVENTER.RNAME.REGION_ENTER elif region.region_shape == UWEB.REGION_SHAPE.POLYGON: polygon = {'name':'', 'points':[]} points = region.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'] = region.region_name if PtInPolygon(location, polygon): region_status = EVENTER.CATEGORY.REGION_ENTER rname = EVENTER.RNAME.REGION_ENTER else: region_status = EVENTER.CATEGORY.REGION_OUT rname = EVENTER.RNAME.REGION_OUT else: #NOTE: here should never occur. logging.error("[EVENTER] unknow region_shape: %s, region: %s, skip it", region.region_shape, region) if old_region_time: if int(location['gps_time']) <= int(old_region_time): logging.info("[EVENTER] current location's gps_time: %s is not bigger than old_region_time: %s, skip it", location['gps_time'], old_region_time) return location # keep region status self.redis.setvalue(old_region_status_key, region_status) logging.info("rname:%s, old status:%s, current status:%s, tid:%s", safe_unicode(region.region_name), old_region_status, region_status, location['dev_id']) if not old_region_status: logging.info("[EVENTER] old_region_status: %s is invalid, skip it", old_region_status) # skip the first region event return location # check region event if region_status != old_region_status: self.redis.setvalue(old_region_status_key, region_status) self.redis.setvalue(old_region_time_key, location['gps_time']) # 2: complete the location location['category'] = region_status location['t'] = EVENTER.INFO_TYPE.REPORT #NOTE: t is need location['rName'] = rname location['region'] = region location['region_id'] = region.region_id return 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
def handle_stop(self, tid, start_time, end_time): track = self.get_track(tid, start_time, end_time) print 'track', len(track) cnt = 0 for i, pvt in enumerate(track): #print 'i: %s, speed: %s, pvt: %s' % (i, pvt['speed'], pvt) stop_key = 'test_stop_redis:%s' % tid stop = self.redis.getvalue(stop_key) distance_key = 'test_distance_redis:%s' % tid distance = self.redis.get(distance_key) if not distance: distance = 0 last_pvt_key = 'test_last_pvt_redis:%s' % tid last_pvt = self.redis.getvalue(last_pvt_key) if last_pvt: tmp = get_distance(int(last_pvt["longitude"]), int(last_pvt["latitude"]), int(pvt["longitude"]), int(pvt["latitude"])) print 'tmp: %s, distance: %s' % (tmp, distance) distance = float(distance) + tmp print 'last distance: %s' % (distance) #print 'add distance', i, pvt['id'], tmp, distance self.redis.setvalue(distance_key, distance, time=EVENTER.STOP_EXPIRY) if pvt['speed'] > LIMIT.SPEED_LIMIT: # 5 is moving if stop: #NOTE: time_diff is too short, drop the point. if pvt["timestamp"] - stop['start_time'] < 60: # 60 seconds cnt += 1 _stop = self.db.get("select distance from T_STOP where lid =%s", stop['lid']) if _stop: tmp_dis = _stop['distance'] else: tmp_dis = 0 print 'tmp_dis', tmp_dis distance = float(distance) + tmp_dis print 'tmp_dis distance', distance 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 cnt += 1 self.redis.delete(stop_key) self.db.execute("UPDATE T_STOP SET end_time = %s WHERE lid = %s", pvt["timestamp"], stop['lid']) logging.info("[EVENTER] Stop point is closed: %s", stop) else: pass else: # low speed, may stop if stop: stop['end_time'] = pvt["timestamp"] self.redis.setvalue(stop_key, stop, time=EVENTER.STOP_EXPIRY) logging.info("[EVENTER] Stop point is updated: %s", stop) else: # NOTE: start stop. #NOTE: create a new stop point cnt += 1 lid=pvt['id'] stop = dict(lid=lid, tid=tid, start_time=pvt["timestamp"], end_time=0, pre_lon=pvt["longitude"], pre_lat=pvt["latitude"], distance=distance) self.db.execute("INSERT INTO T_STOP(lid, tid, start_time, distance) VALUES(%s, %s, %s, %s)", lid, tid, pvt["timestamp"], 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) last_pvt = pvt self.redis.setvalue(last_pvt_key, last_pvt, time=EVENTER.STOP_EXPIRY) print '---------------------- cnt', cnt
def _on_finish(db): self.db = db page_count = int(data.pagecnt) if statistic_mode == 'all': # all if page_count == -1: count = len(tids) d, m = divmod(count, page_size) page_count = (d + 1) if m else d reports = [] for item, tid in enumerate(tids): seq=item+1 dis_sum = Decimal() start_date = get_date_from_utc(start_time) end_date = get_date_from_utc(end_time) start_day = datetime.datetime.fromtimestamp(start_time) end_day = datetime.datetime.fromtimestamp(end_time) # get how many days the end_time and start_time cover days = abs(end_day-start_day).days+1 for item in range(days): distance = Decimal() timestamp = start_time+1*60*60*24*(item) date = get_date_from_utc(timestamp) year, month, day = date.year, date.month, date.day start_time_, end_time_ = start_end_of_day(year=year, month=month, day=day) points = self.db.query("SELECT longitude, latitude FROM T_LOCATION" " WHERE tid = %s" " AND (timestamp BETWEEN %s AND %s)" " AND type = 0" " ORDER BY timestamp asc", tid, start_time_+start_period_, start_time_+end_period_) for i in range(len(points)-1): if points[i].longitude and points[i].latitude and \ points[i+1].longitude and points[i+1].latitude: dis = get_distance(points[i].longitude, points[i].latitude, points[i+1].longitude, points[i+1].latitude) distance += Decimal(str(dis)) # meter --> km distance = '%0.1f' % (distance/1000,) dis_sum += Decimal(distance) alias = QueryHelper.get_alias_by_tid(tid, self.redis, self.db) dct = dict(seq=seq, alias=alias, distance=float(dis_sum)) reports.append(dct) # orgnize and store the data to be downloaded m = hashlib.md5() m.update(self.request.body) hash_ = m.hexdigest() mem_key = self.KEY_TEMPLATE % (self.current_user.uid, hash_) self.redis.setvalue(mem_key, (statistic_mode, reports, 0), time=UWEB.STATISTIC_INTERVAL) reports= reports[(page_number * page_size):((page_number+1) * page_size)] self.write_ret(status, dict_=DotDict(res=reports, pagecnt=page_count, hash_=hash_)) else: # single tid = tids[0] delta = end_time - start_time # end_time must bigger than start_time d, m = divmod(delta, 60*60*24) start_date = get_date_from_utc(start_time) end_date = get_date_from_utc(end_time) start_day = datetime.datetime.fromtimestamp(start_time) end_day = datetime.datetime.fromtimestamp(end_time) # get how many days the end_time and start_time cover days = abs(end_day-start_day).days+1 #if days == 0: # if start_date.day == end_date.day: # days = 1 # else: # days = 2 #else: # days = days+1 if m else days # if end_day.hour*60*60 + end_day.minute*60 + end_day.second < start_day.hour*60*60 + start_day.minute*60 + start_day.second: # days = days+1 res = [] graphics = [] counts = [] dis_sum = Decimal() current_time = int(time.time()) sql_cmd = ("SELECT longitude, latitude FROM T_LOCATION" " WHERE tid = %s" " AND (timestamp BETWEEN %s AND %s)" " AND type = 0" " ORDER BY timestamp asc") #last_cmd = ("SELECT timestamp FROM T_LOCATION" # " WHERE tid = %s" # " AND (timestamp BETWEEN %s AND %s)" # " AND type = 0" # " ORDER BY timestamp desc limit 1") #next_cmd = ("SELECT timestamp FROM T_LOCATION" # " WHERE tid = %s" # " AND (timestamp BETWEEN %s AND %s)" # " AND type = 0" # " ORDER BY timestamp asc limit 1") if days == 1: # start_time, end_time in the same day timestamp = start_time date = get_date_from_utc(timestamp) re = {} re['alias'] = '-'.join([str(date.year),str(date.month),str(date.day)]) distance = Decimal() points = self.db.query(sql_cmd, tid, start_time+start_period_, start_time+end_period_) for i in range(len(points)-1): if points[i].longitude and points[i].latitude and \ points[i+1].longitude and points[i+1].latitude: dis = get_distance(points[i].longitude, points[i].latitude, points[i+1].longitude, points[i+1].latitude) distance += Decimal(str(dis)) # meter --> km distance = '%0.1f' % (distance/1000,) graphics.append(float(distance)) dis_sum += Decimal(distance) re['distance'] = distance re['seq'] = 1 res.append(re) else: # start_time, end_time in different days for item in range(days): timestamp = start_time+1*60*60*24*(item) date = get_date_from_utc(timestamp) year, month, day = date.year, date.month, date.day start_time_, end_time_ = start_end_of_day(year=year, month=month, day=day) ## handle the first day and last day #if item == 0: # start_time_ = start_time #if item == days: # end_time_ = end_time #last_point = self.db.get(last_cmd, tid, start_time_-60*60*24, start_time_,) #next_point = self.db.get(next_cmd, tid, end_time_, end_time_+60*60*24) #start_time_ = last_point['timestamp'] if last_point else start_time_ #end_time_ = next_point['timestamp'] if next_point else end_time_ re = {} re['alias'] = '-'.join([str(year),str(month),str(day)]) distance = Decimal() points = self.db.query(sql_cmd, tid, start_time_+start_period_, start_time_+end_period_) for i in range(len(points)-1): if points[i].longitude and points[i].latitude and \ points[i+1].longitude and points[i+1].latitude: dis = get_distance(points[i].longitude, points[i].latitude, points[i+1].longitude, points[i+1].latitude) distance += Decimal(str(dis)) # meter --> km distance = '%0.1f' % (distance/1000,) graphics.append(float(distance)) dis_sum += Decimal(distance) re['distance'] = distance re['seq'] = item+1 res.append(re) counts = [float(dis_sum),] if page_count == -1: items_count = len(res) d, m = divmod(items_count, page_size) page_count = (d + 1) if m else d # store resutl in redis m = hashlib.md5() m.update(self.request.body) hash_ = m.hexdigest() mem_key = self.KEY_TEMPLATE % (self.current_user.uid, hash_) self.redis.setvalue(mem_key, (statistic_mode, res, counts,), time=UWEB.STATISTIC_INTERVAL) res= res[page_number*page_size:(page_number+1)*page_size] self.write_ret(status, dict_=dict(res=res, counts=counts, graphics=graphics, pagecnt=page_count, hash_=hash_)) self.finish()
def post(self): """Provide statistics about terminal. """ status = ErrorCode.SUCCESS try: data = DotDict(json_decode(self.request.body)) logging.info("[UWEB] statistic request: %s, uid: %s, tid: %s", data, self.current_user.uid, self.current_user.tid) except Exception as e: status = ErrorCode.ILLEGAL_DATA_FORMAT self.write_ret(status) return try: page_size = UWEB.LIMIT.PAGE_SIZE_STATISTICS page_number = int(data.pagenum) page_count = int(data.pagecnt) tid = data.tid res = [] graphics = [] counts = [] label = u'' sql_cmd = ("SELECT longitude, latitude FROM T_LOCATION" " WHERE tid = %s" " AND (timestamp BETWEEN %s AND %s)" " AND type = 0" " ORDER BY timestamp asc") last_cmd = ("SELECT timestamp FROM T_LOCATION" " WHERE tid = %s" " AND (timestamp BETWEEN %s AND %s)" " AND type = 0" " ORDER BY timestamp desc limit 1") next_cmd = ("SELECT timestamp FROM T_LOCATION" " WHERE tid = %s" " AND (timestamp BETWEEN %s AND %s)" " AND type = 0" " ORDER BY timestamp asc limit 1") dis_sum = Decimal() current_time = int(time.time()) statistics_type = data.statistics_type if statistics_type == UWEB.STATISTICS_TYPE.YEAR: label = data.year + u'年' start_time, end_time = start_end_of_year(year=data.year) for month in range(1,12+1): start_time_, end_time_ = start_end_of_month(year=data.year, month=str(month)) if start_time_ > current_time: break re = {} re['name'] = str(month) distance = Decimal() points = self.db.query(sql_cmd, tid, start_time_, end_time_) for i in range(len(points)-1): if points[i].longitude and points[i].latitude and \ points[i+1].longitude and points[i+1].latitude: dis = get_distance(points[i].longitude, points[i].latitude, points[i+1].longitude, points[i+1].latitude) distance += Decimal(str(dis)) # meter --> km distance = '%0.1f' % (distance/1000,) if float(distance) == 0: distance = 0 graphics.append(float(distance)) dis_sum += Decimal(distance) re['mileage'] = distance res.append(re) counts = [float(dis_sum),] elif statistics_type == UWEB.STATISTICS_TYPE.MONTH: label = data.year + u'年' + data.month + u'月' start_time, end_time = start_end_of_month(year=data.year, month=data.month) days = days_of_month(year=data.year, month=data.month) distance = Decimal() points_ = self.db.query(sql_cmd, tid, start_time, end_time) for i in range(len(points_)-1): if points_[i].longitude and points_[i].latitude and \ points_[i+1].longitude and points_[i+1].latitude: dis = get_distance(points_[i].longitude, points_[i].latitude, points_[i+1].longitude, points_[i+1].latitude) dis=Decimal(str(dis)) distance += dis distance = '%0.1f' % (distance/1000,) dis_sum = distance for day in range(1,days+1): start_time_, end_time_ = start_end_of_day(year=data.year, month=data.month, day=str(day)) if start_time_ > current_time: break last_point = self.db.get(last_cmd, tid, start_time_-60*60*24, start_time_,) next_point = self.db.get(next_cmd, tid, end_time_, end_time_+60*60*24) start_time_ = last_point['timestamp'] if last_point else start_time_ end_time_ = next_point['timestamp'] if next_point else end_time_ re = {} re['name'] = str(day) distance = Decimal() points = self.db.query(sql_cmd, tid, start_time_, end_time_) for i in range(len(points)-1): if points[i].longitude and points[i].latitude and \ points[i+1].longitude and points[i+1].latitude: dis = get_distance(points[i].longitude, points[i].latitude, points[i+1].longitude, points[i+1].latitude) distance += Decimal(str(dis)) # meter --> km distance = '%0.1f' % (distance/1000,) if float(distance) == 0: distance = 0 graphics.append(float(distance)) re['mileage'] = distance res.append(re) counts = [float(dis_sum),] else: logging.error("[UWEB] Error statistics type: %s", statistics_type) if page_count == -1: items_count = len(res) d, m = divmod(items_count, page_size) page_count = (d + 1) if m else d # store resutl in redis m = hashlib.md5() m.update(self.request.body) hash_ = m.hexdigest() mem_key = self.KEY_TEMPLATE % (self.current_user.uid, hash_) self.redis.setvalue(mem_key, (res, counts, label, statistics_type), time=UWEB.STATISTIC_INTERVAL) res= res[page_number*page_size:(page_number+1)*page_size] self.write_ret(status, dict_=dict(res=res, counts=counts, graphics=graphics, pagecnt=page_count, hash_=hash_)) except Exception as e: logging.exception("[UWEB] uid:%s, tid:%s statistic failed. Exception: %s", self.current_user.uid, self.current_user.tid, e.args) status = ErrorCode.SERVER_BUSY self.write_ret(status)