Переглянути джерело

增加火焰检测类型/实现往来检测客流统计接口

zhangdongming 2 роки тому
батько
коміт
a8d66034ab

+ 151 - 2
Controller/AlgorithmShop/AlgorithmShopController.py

@@ -8,10 +8,11 @@
 """
 import json
 import logging
+import math
 import time
-from datetime import datetime
+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 Model.models import DeviceAlgorithmExplain, DeviceAlgorithmBanner, DeviceUidAlgorithmType, \
@@ -58,6 +59,8 @@ class AlgorithmShopView(View):
             return self.get_scenario_list(request_dict, response)
         elif operation == 'getAlgorithmListByScenarioId':  # 根据应用场景id获取算法列表
             return self.get_scenario_algorithm_list(request_dict, response)
+        elif operation == 'getPassengerFlowList':  # 获取客流统计列表
+            return self.get_passenger_flow_list(request_dict, response)
         else:
             return response.json(0)
 
@@ -438,3 +441,149 @@ class AlgorithmShopView(View):
         except Exception as e:
             print('保存算法设置异常,errLine:{}, errMsg:{}'.format(e.__traceback__.tb_lineno, 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__in=t_list,
+            type=int(flow_type),
+            uid=uid
+        ).order_by('device_time')
+        if not pf_qs.exists():
+            return passenger_flow_list
+        # 将查询到的数据时间戳转字典
+        pf_dict = {pf.device_time: pf for pf in pf_qs}
+        # 循环查找最近24小时的记录(包含当前时间)
+        for i in range(24):
+            current_timestamp = t_list[i]
+            if current_timestamp in pf_dict:
+                item = pf_dict[current_timestamp]
+                passenger_flow_list.append({
+                    'index': 23 - i,
+                    'count': item.count,
+                    'time': item.device_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 = []
+
+            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)
+
+            if days_qs:
+                # 将每天的客流数据统计结果添加到列表中
+                passenger_flow_list.append({
+                    'index': 29 - i,
+                    '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))
+            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))
+            df_qs = df_qs.aggregate(total=Sum('count'))
+            if not df_qs['total']:
+                continue
+
+            passenger_flow_list.append({
+                'index': 11 - i,
+                'count': df_qs['total'],
+                'time': month_time
+            })
+        return passenger_flow_list

+ 1 - 1
Model/models.py

@@ -3081,7 +3081,7 @@ class DeviceAlgorithmScenario(models.Model):
 class DeviceAlgorithmType(models.Model):
     id = models.AutoField(primary_key=True)
     # 0:移动侦测,1:人形检测,2:挥手识别,3:人脸检测,4:异声感知,5:车辆检测,7:宠物检测,6:哭声检测,8:徘徊检测
-    # 9:区域闯入,10:区域闯出,11:长时间无人检测,12:往来检测,13:云相册
+    # 9:区域闯入,10:区域闯出,11:长时间无人检测,12:往来检测,13:云相册,14:火焰检测
     type = models.SmallIntegerField(default=0, verbose_name='算法类型')
     memory = models.CharField(max_length=32, default='', verbose_name='所需内存')
     down_count = models.IntegerField(default=0, verbose_name='下载次数')

+ 39 - 0
Object/utils/LocalDateTimeUtil.py

@@ -269,3 +269,42 @@ def time_format_date(timestamp, tz):
     formatted_date = dt.strftime('%Y-%m-%d %H:%M:%S')
     return formatted_date
 
+
+def start_of_day_timestamp(timestamp):
+    # 将当前时间戳转换为 datetime 对象
+    dt = datetime.datetime.fromtimestamp(timestamp)
+
+    # 获取日期部分,并将时、分、秒和微秒设置为零
+    dt_start_of_day = dt.replace(hour=0, minute=0, second=0, microsecond=0)
+
+    return int(dt_start_of_day.timestamp())
+
+
+def get_previous_month_first_day(timestamp):
+    # 将时间戳转换为datetime对象
+    dt = datetime.datetime.fromtimestamp(timestamp)
+
+    # 获取上个月的年份和月份
+    previous_month_year = dt.year if dt.month > 1 else dt.year - 1
+    previous_month = dt.month - 1 if dt.month > 1 else 12
+
+    # 构造上个月第一天的datetime对象
+    previous_month_first_day = datetime.datetime(previous_month_year, previous_month, 1)
+
+    # 将上个月第一天的datetime对象转换为时间戳并返回
+    return int(previous_month_first_day.timestamp())
+
+
+def get_current_month_first_day(timestamp):
+    # 将时间戳转换为datetime对象
+    dt = datetime.datetime.fromtimestamp(timestamp)
+
+    # 获取当前月份的年份和月份
+    current_month_year = dt.year
+    current_month = dt.month
+
+    # 构造当前月份第一天的datetime对象
+    current_month_first_day = datetime.datetime(current_month_year, current_month, 1)
+
+    # 将当前月份第一天的datetime对象转换为时间戳并返回
+    return int(current_month_first_day.timestamp())