|
@@ -6,16 +6,24 @@
|
|
@Email : zhangdongming@asj6.wecom.work
|
|
@Email : zhangdongming@asj6.wecom.work
|
|
@Software: PyCharm
|
|
@Software: PyCharm
|
|
"""
|
|
"""
|
|
|
|
+import json
|
|
import logging
|
|
import logging
|
|
|
|
+import math
|
|
import time
|
|
import time
|
|
|
|
+from datetime import datetime, timedelta
|
|
|
|
|
|
-from django.db.models import F, Value, CharField
|
|
|
|
|
|
+from django.db.models import F, Value, CharField, Sum
|
|
from django.views.generic.base import View
|
|
from django.views.generic.base import View
|
|
|
|
|
|
from Model.models import DeviceAlgorithmExplain, DeviceAlgorithmBanner, DeviceUidAlgorithmType, \
|
|
from Model.models import DeviceAlgorithmExplain, DeviceAlgorithmBanner, DeviceUidAlgorithmType, \
|
|
- DeviceTypeAlgorithmInfo, DeviceAppScenario, DeviceScenarioLangInfo, DeviceAlgorithmScenario
|
|
|
|
|
|
+ DeviceTypeAlgorithmInfo, DeviceAppScenario, DeviceScenarioLangInfo, DeviceAlgorithmScenario, \
|
|
|
|
+ DeviceAlgorithmPassengerFlow
|
|
|
|
+from Object.ETkObject import ETkObject
|
|
|
|
+from Object.Enums.TimeZone import TimeZone
|
|
|
|
+from Object.RedisObject import RedisObject
|
|
from Object.ResponseObject import ResponseObject
|
|
from Object.ResponseObject import ResponseObject
|
|
from Object.TokenObject import TokenObject
|
|
from Object.TokenObject import TokenObject
|
|
|
|
+from Object.utils import LocalDateTimeUtil
|
|
|
|
|
|
LOGGER = logging.getLogger('info')
|
|
LOGGER = logging.getLogger('info')
|
|
|
|
|
|
@@ -32,6 +40,8 @@ class AlgorithmShopView(View):
|
|
return self.validation(request.POST, request, operation)
|
|
return self.validation(request.POST, request, operation)
|
|
|
|
|
|
def validation(self, request_dict, request, operation):
|
|
def validation(self, request_dict, request, operation):
|
|
|
|
+ if operation == 'passengerFlowStatistical':
|
|
|
|
+ return self.passenger_flow_statistical(request_dict, ResponseObject('en'))
|
|
token = TokenObject(request.META.get('HTTP_AUTHORIZATION'))
|
|
token = TokenObject(request.META.get('HTTP_AUTHORIZATION'))
|
|
lang = request_dict.get('lang', token.lang)
|
|
lang = request_dict.get('lang', token.lang)
|
|
response = ResponseObject(lang)
|
|
response = ResponseObject(lang)
|
|
@@ -49,9 +59,75 @@ class AlgorithmShopView(View):
|
|
return self.get_scenario_list(request_dict, response)
|
|
return self.get_scenario_list(request_dict, response)
|
|
elif operation == 'getAlgorithmListByScenarioId': # 根据应用场景id获取算法列表
|
|
elif operation == 'getAlgorithmListByScenarioId': # 根据应用场景id获取算法列表
|
|
return self.get_scenario_algorithm_list(request_dict, response)
|
|
return self.get_scenario_algorithm_list(request_dict, response)
|
|
|
|
+ elif operation == 'getPassengerFlowList': # 获取客流统计列表
|
|
|
|
+ return self.get_passenger_flow_list(request_dict, response)
|
|
else:
|
|
else:
|
|
return response.json(0)
|
|
return response.json(0)
|
|
|
|
|
|
|
|
+ @classmethod
|
|
|
|
+ def passenger_flow_statistical(cls, request_dict, response):
|
|
|
|
+ """
|
|
|
|
+ 添加客流统计
|
|
|
|
+ Args:
|
|
|
|
+ request_dict (dict): 请求参数字典
|
|
|
|
+ response: 响应对象
|
|
|
|
+ """
|
|
|
|
+ try:
|
|
|
|
+ LOGGER.info('*****AlgorithmShopView.passenger_flow_statistical:params{}'.format(json.dumps(request_dict)))
|
|
|
|
+ sign = request_dict.get('sign')
|
|
|
|
+ eto = ETkObject(sign)
|
|
|
|
+ uid = eto.uid
|
|
|
|
+ if not uid:
|
|
|
|
+ return response.json(444)
|
|
|
|
+
|
|
|
|
+ d_time = request_dict.get('deviceTime')
|
|
|
|
+ enter_count = request_dict.get('enterCount')
|
|
|
|
+ tz_value = request_dict.get('timeZone')
|
|
|
|
+ exit_count = request_dict.get('exitCount')
|
|
|
|
+
|
|
|
|
+ if not all([sign, enter_count, exit_count, tz_value]):
|
|
|
|
+ return response.json(444)
|
|
|
|
+ enter_count = int(enter_count)
|
|
|
|
+ exit_count = int(exit_count)
|
|
|
|
+ redis = RedisObject(5)
|
|
|
|
+ key = f'ASJ:PASSENGER:FLOW:{uid}:{d_time}'
|
|
|
|
+
|
|
|
|
+ # 检查Redis中是否已存在相同key的数据
|
|
|
|
+ r_data = redis.get_data(key)
|
|
|
|
+ if r_data:
|
|
|
|
+ return response.json(0)
|
|
|
|
+
|
|
|
|
+ now_time = int(time.time())
|
|
|
|
+ data = {
|
|
|
|
+ 'uid': uid,
|
|
|
|
+ 'updated_time': now_time,
|
|
|
|
+ 'created_time': now_time,
|
|
|
|
+ 'device_time': int(d_time)
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ tz = TimeZone.get_value(int(tz_value))
|
|
|
|
+ date_time = LocalDateTimeUtil.time_format_date(int(d_time), tz)
|
|
|
|
+ data['statistical_time'] = datetime.strptime(date_time, '%Y-%m-%d %H:%M:%S')
|
|
|
|
+
|
|
|
|
+ LOGGER.info(f'uid{uid}-DeviceTime:{d_time},tz:{tz},结果:{date_time}')
|
|
|
|
+ passenger_flow_list = []
|
|
|
|
+ data['count'] = enter_count
|
|
|
|
+ data['type'] = 1
|
|
|
|
+ passenger_flow_list.append(DeviceAlgorithmPassengerFlow(**data))
|
|
|
|
+ data['count'] = exit_count
|
|
|
|
+ data['type'] = 2
|
|
|
|
+ passenger_flow_list.append(DeviceAlgorithmPassengerFlow(**data))
|
|
|
|
+ DeviceAlgorithmPassengerFlow.objects.bulk_create(passenger_flow_list)
|
|
|
|
+ # 将数据存入Redis,并设置过期时间为10分钟
|
|
|
|
+ redis.CONN.setnx(key, d_time)
|
|
|
|
+ redis.CONN.expire(key, 600)
|
|
|
|
+
|
|
|
|
+ return response.json(0)
|
|
|
|
+ except Exception as e:
|
|
|
|
+ LOGGER.info('***get_algorithm_list_by_scenario_id,errLine:{}, errMsg:{}'
|
|
|
|
+ .format(e.__traceback__.tb_lineno, repr(e)))
|
|
|
|
+ return response.json(500, 'error_line:{}, error_msg:{}'.format(e.__traceback__.tb_lineno, repr(e)))
|
|
|
|
+
|
|
@classmethod
|
|
@classmethod
|
|
def get_algorithm_list_by_scenario_id(cls, scenario_id, lang):
|
|
def get_algorithm_list_by_scenario_id(cls, scenario_id, lang):
|
|
"""
|
|
"""
|
|
@@ -191,7 +267,7 @@ class AlgorithmShopView(View):
|
|
return response.json(0, result_dto)
|
|
return response.json(0, result_dto)
|
|
except Exception as e:
|
|
except Exception as e:
|
|
LOGGER.info('接口异常,errLine:{}, errMsg:{}'.format(e.__traceback__.tb_lineno, repr(e)))
|
|
LOGGER.info('接口异常,errLine:{}, errMsg:{}'.format(e.__traceback__.tb_lineno, repr(e)))
|
|
- return response.json(500, repr(e))
|
|
|
|
|
|
+ return response.json(500, 'error_line:{}, error_msg:{}'.format(e.__traceback__.tb_lineno, repr(e)))
|
|
|
|
|
|
@classmethod
|
|
@classmethod
|
|
def get_scenario_algorithm_list(cls, request_dist, response):
|
|
def get_scenario_algorithm_list(cls, request_dist, response):
|
|
@@ -269,7 +345,7 @@ class AlgorithmShopView(View):
|
|
return response.json(0, algorithm_list)
|
|
return response.json(0, algorithm_list)
|
|
except Exception as e:
|
|
except Exception as e:
|
|
print('查询算法小店列表异常,errLine:{}, errMsg:{}'.format(e.__traceback__.tb_lineno, repr(e)))
|
|
print('查询算法小店列表异常,errLine:{}, errMsg:{}'.format(e.__traceback__.tb_lineno, repr(e)))
|
|
- return response.json(500, repr(e))
|
|
|
|
|
|
+ return response.json(500, 'error_line:{}, error_msg:{}'.format(e.__traceback__.tb_lineno, repr(e)))
|
|
|
|
|
|
@classmethod
|
|
@classmethod
|
|
def get_algorithm_details(cls, request_dict, response):
|
|
def get_algorithm_details(cls, request_dict, response):
|
|
@@ -363,3 +439,168 @@ class AlgorithmShopView(View):
|
|
except Exception as e:
|
|
except Exception as e:
|
|
print('保存算法设置异常,errLine:{}, errMsg:{}'.format(e.__traceback__.tb_lineno, repr(e)))
|
|
print('保存算法设置异常,errLine:{}, errMsg:{}'.format(e.__traceback__.tb_lineno, repr(e)))
|
|
return response.json(177, repr(e))
|
|
return response.json(177, repr(e))
|
|
|
|
+
|
|
|
|
+ @classmethod
|
|
|
|
+ def get_passenger_flow_list(cls, request_dict, response):
|
|
|
|
+ """
|
|
|
|
+ 获取客流统计列表
|
|
|
|
+ """
|
|
|
|
+ try:
|
|
|
|
+ uid = request_dict.get('uid')
|
|
|
|
+ now_time = request_dict.get('nowTime')
|
|
|
|
+ flow_type = request_dict.get('flowType')
|
|
|
|
+ query_type = request_dict.get('queryType')
|
|
|
|
+ if not all([now_time, flow_type, query_type]):
|
|
|
|
+ return response.json(444)
|
|
|
|
+ query_type = int(query_type)
|
|
|
|
+ flow_type = int(flow_type)
|
|
|
|
+ passenger_flow_list = []
|
|
|
|
+ # 将需要查询的时间戳列表拼接成缓存的键名
|
|
|
|
+ cache_key = f"ASJ:PASSENGER_FLOW:{uid}_{flow_type}_{query_type}_{now_time}"
|
|
|
|
+ redis = RedisObject(5)
|
|
|
|
+ passenger_flow_json = redis.get_data(cache_key)
|
|
|
|
+ if passenger_flow_json:
|
|
|
|
+ return response.json(0, json.loads(passenger_flow_json))
|
|
|
|
+ if query_type == 1:
|
|
|
|
+ passenger_flow_list = cls.get_passenger_flow_by_day(uid, int(now_time), flow_type)
|
|
|
|
+ elif query_type == 2:
|
|
|
|
+ passenger_flow_list = cls.get_passenger_flow_by_month(uid, int(now_time), flow_type)
|
|
|
|
+ elif query_type == 3:
|
|
|
|
+ passenger_flow_list = cls.get_passenger_flow_by_year(uid, int(now_time), flow_type)
|
|
|
|
+ else:
|
|
|
|
+ return response.json(0, passenger_flow_list)
|
|
|
|
+ if passenger_flow_list:
|
|
|
|
+ redis.CONN.setnx(cache_key, json.dumps(passenger_flow_list))
|
|
|
|
+ redis.CONN.expire(cache_key, 3600 * 24)
|
|
|
|
+ return response.json(0, passenger_flow_list)
|
|
|
|
+ except Exception as e:
|
|
|
|
+ print('查询客流异常,errLine:{}, errMsg:{}'.format(e.__traceback__.tb_lineno, repr(e)))
|
|
|
|
+ return response.json(500, repr(e))
|
|
|
|
+
|
|
|
|
+ @staticmethod
|
|
|
|
+ def get_passenger_flow_by_day(uid, now_time, flow_type):
|
|
|
|
+ """
|
|
|
|
+ 按天获取客流统计
|
|
|
|
+ """
|
|
|
|
+ c_time = datetime.fromtimestamp(int(now_time))
|
|
|
|
+ # 一天周期24小时从当前小时整点往前查询近24小时,生成秒级时间戳
|
|
|
|
+ t_list = [math.floor((c_time - timedelta(hours=i)).timestamp()) for i in range(24)]
|
|
|
|
+ passenger_flow_list = []
|
|
|
|
+ pf_qs = DeviceAlgorithmPassengerFlow.objects.filter(
|
|
|
|
+ device_time__gte=t_list[23],
|
|
|
|
+ device_time__lte=t_list[0] + 60,
|
|
|
|
+ type=int(flow_type),
|
|
|
|
+ uid=uid
|
|
|
|
+ ).order_by('device_time')
|
|
|
|
+ if not pf_qs.exists():
|
|
|
|
+ return passenger_flow_list
|
|
|
|
+ # 循环查找最近24小时的记录(包含当前时间)
|
|
|
|
+ for i in range(24):
|
|
|
|
+ current_time = t_list[i]
|
|
|
|
+ next_time = -1 if i == 0 else t_list[i - 1]
|
|
|
|
+ is_data = False
|
|
|
|
+ count = 0
|
|
|
|
+ hour = 0
|
|
|
|
+ for item in pf_qs:
|
|
|
|
+ if next_time == -1 and next_time == item.device_time:
|
|
|
|
+ hour = item.statistical_time.hour
|
|
|
|
+ count += item.count
|
|
|
|
+ is_data = True
|
|
|
|
+ elif current_time <= item.device_time < next_time:
|
|
|
|
+ count += item.count
|
|
|
|
+ hour = item.statistical_time.hour
|
|
|
|
+ is_data = True
|
|
|
|
+ elif next_time == -1 and current_time <= item.device_time:
|
|
|
|
+ hour = item.statistical_time.hour
|
|
|
|
+ count += item.count
|
|
|
|
+ is_data = True
|
|
|
|
+ if not is_data:
|
|
|
|
+ continue
|
|
|
|
+ passenger_flow_list.append({
|
|
|
|
+ 'index': hour,
|
|
|
|
+ 'count': count,
|
|
|
|
+ 'time': current_time
|
|
|
|
+ })
|
|
|
|
+ return passenger_flow_list
|
|
|
|
+
|
|
|
|
+ @staticmethod
|
|
|
|
+ def get_passenger_flow_by_month(uid, now_time, flow_type):
|
|
|
|
+ """
|
|
|
|
+ 按月获取客流统计
|
|
|
|
+ """
|
|
|
|
+
|
|
|
|
+ # 获取30天前的时间戳作为起始时间
|
|
|
|
+ s_time = LocalDateTimeUtil.get_before_days_timestamp(now_time, 30)
|
|
|
|
+ # 将起始时间设置为当天的开始时间
|
|
|
|
+ s_time = LocalDateTimeUtil.start_of_day_timestamp(s_time)
|
|
|
|
+
|
|
|
|
+ # 查询指定类型的客流数据,按设备时间升序排序
|
|
|
|
+ pf_qs = DeviceAlgorithmPassengerFlow.objects.filter(
|
|
|
|
+ device_time__range=(s_time, now_time),
|
|
|
|
+ type=int(flow_type),
|
|
|
|
+ uid=uid
|
|
|
|
+ ).order_by('device_time')
|
|
|
|
+
|
|
|
|
+ passenger_flow_list = []
|
|
|
|
+ if not pf_qs.exists():
|
|
|
|
+ return passenger_flow_list
|
|
|
|
+
|
|
|
|
+ for i in range(30): # 查询月按30天为一个周期
|
|
|
|
+ if i == 0:
|
|
|
|
+ # 当天的开始时间作为查询的起始时间
|
|
|
|
+ s_time = LocalDateTimeUtil.start_of_day_timestamp(now_time)
|
|
|
|
+ else:
|
|
|
|
+ # 获取i天前的时间戳作为查询的起始时间
|
|
|
|
+ s_time = LocalDateTimeUtil.get_before_days_timestamp(now_time, i)
|
|
|
|
+ # 将起始时间设置为当天的开始时间
|
|
|
|
+ s_time = LocalDateTimeUtil.start_of_day_timestamp(s_time)
|
|
|
|
+
|
|
|
|
+ days_qs = []
|
|
|
|
+ day = 0
|
|
|
|
+ for item in pf_qs:
|
|
|
|
+ # 计算结束时间
|
|
|
|
+ end_time = now_time if i == 0 else s_time + (3600 * 24)
|
|
|
|
+
|
|
|
|
+ # 将在起始时间和结束时间范围内的客流数据放入列表中
|
|
|
|
+ if s_time < item.device_time <= end_time:
|
|
|
|
+ days_qs.append(item.count)
|
|
|
|
+ day = item.statistical_time.day if day == 0 else day
|
|
|
|
+
|
|
|
|
+ if days_qs:
|
|
|
|
+ # 将每天的客流数据统计结果添加到列表中
|
|
|
|
+ passenger_flow_list.append({
|
|
|
|
+ 'index': day,
|
|
|
|
+ 'count': sum(days_qs),
|
|
|
|
+ 'time': s_time
|
|
|
|
+ })
|
|
|
|
+
|
|
|
|
+ return passenger_flow_list
|
|
|
|
+
|
|
|
|
+ @staticmethod
|
|
|
|
+ def get_passenger_flow_by_year(uid, now_time, flow_type):
|
|
|
|
+ """
|
|
|
|
+ 按年获取客流统计
|
|
|
|
+ """
|
|
|
|
+ month_time = 0
|
|
|
|
+ passenger_flow_list = []
|
|
|
|
+ for i in range(12):
|
|
|
|
+ if i == 0:
|
|
|
|
+ month_time = LocalDateTimeUtil.get_current_month_first_day(now_time)
|
|
|
|
+ df_qs = DeviceAlgorithmPassengerFlow.objects.filter(type=flow_type, uid=uid)
|
|
|
|
+ if i == 0:
|
|
|
|
+ df_qs = df_qs.filter(device_time__range=(month_time, now_time))
|
|
|
|
+ data_qs = df_qs.first()
|
|
|
|
+ else:
|
|
|
|
+ previous_month_time = LocalDateTimeUtil.get_previous_month_first_day(month_time)
|
|
|
|
+ df_qs = df_qs.filter(device_time__range=(previous_month_time, month_time))
|
|
|
|
+ data_qs = df_qs.first()
|
|
|
|
+ month_time = previous_month_time
|
|
|
|
+ df_qs = df_qs.aggregate(total=Sum('count'))
|
|
|
|
+ if not df_qs['total']:
|
|
|
|
+ continue
|
|
|
|
+ passenger_flow_list.append({
|
|
|
|
+ 'index': data_qs.statistical_time.month,
|
|
|
|
+ 'count': df_qs['total'],
|
|
|
|
+ 'time': month_time
|
|
|
|
+ })
|
|
|
|
+ return passenger_flow_list
|