Browse Source

Merge branch 'test' of http://192.168.136.99:3000/servers/ASJServer

 Conflicts:
	AdminController/UnicomManageController.py
	Controller/EquipmentManagerV3.py
	Controller/UserController.py
peng 3 years ago
parent
commit
13273c23ec
37 changed files with 2632 additions and 796 deletions
  1. 76 1
      AdminController/DeviceManagementController.py
  2. 2 1
      AdminController/LogManagementController.py
  3. 23 25
      AdminController/ServeManagementController.py
  4. 6 0
      Ansjer/Config/__init__.py
  5. 57 0
      Ansjer/Config/gatewaySensorConfig.py
  6. 1 0
      Ansjer/config.py
  7. 2 1
      Ansjer/server_urls/loocam_url.py
  8. 21 0
      Ansjer/urls.py
  9. 2 2
      Controller/AiController.py
  10. 9 7
      Controller/CloudStorage.py
  11. 1 53
      Controller/Cloudsum.py
  12. 78 75
      Controller/DetectController.py
  13. 144 141
      Controller/DetectControllerV2.py
  14. 12 3
      Controller/DeviceShare.py
  15. 60 36
      Controller/EquipmentManager.py
  16. 2 2
      Controller/EquipmentManagerV2.py
  17. 57 51
      Controller/EquipmentManagerV3.py
  18. 25 9
      Controller/IotCoreController.py
  19. 2 2
      Controller/OrderContrller.py
  20. 26 3
      Controller/PaymentCycle.py
  21. 143 6
      Controller/SensorGateway/EquipmentFamilyController.py
  22. 87 3
      Controller/SensorGateway/GatewayDeviceController.py
  23. 11 2
      Controller/SensorGateway/GatewayFamilyMemberController.py
  24. 180 40
      Controller/SensorGateway/GatewayFamilyRoomController.py
  25. 915 0
      Controller/SensorGateway/SmartSceneController.py
  26. 315 90
      Controller/SensorGateway/SubDeviceController.py
  27. 129 26
      Controller/TestApi.py
  28. 95 81
      Controller/UserController.py
  29. 0 17
      Model/models.py
  30. 112 0
      Object/AWS/AmazonS3Util.py
  31. 1 0
      Object/LogsObject.py
  32. 6 2
      Object/ResponseObject.py
  33. 29 5
      Service/CommonService.py
  34. 3 3
      Service/EquipmentInfoService.py
  35. 0 10
      Service/ModelService.py
  36. 0 95
      Service/OperatingLogs.py
  37. 0 4
      Service/middleware.py

+ 76 - 1
AdminController/DeviceManagementController.py

@@ -72,9 +72,73 @@ class DeviceManagement(View):
                 return self.edit_app_device_type(request_dict, response)
             elif operation == 'deleteAppDeviceType':  # 删除app设备类型数据
                 return self.delete_app_device_type(request_dict, response)
+            elif operation == 'addAppDeviceType':  # 添加app设备类型数据
+                return self.add_app_device_type(request_dict, response)
+            elif operation == 'getAppBundle':  # 获取app版本包
+                return self.get_app_bundle(response)
+            elif operation == 'upFile':
+                return self.up_file(request_dict, request, response)
             else:
                 return response.json(444, 'operation')
 
+    @staticmethod
+    def up_file(request_dict, request, response):
+        pass
+
+
+    @classmethod
+    def get_app_bundle(cls, response):
+        app_bundle_qs = AppBundle.objects.all().values('id', 'app_bundle_id')
+        if not app_bundle_qs.exists():
+            return response.json(444)
+        try:
+            app_bundle_list = []
+            for app_bundle in app_bundle_qs:
+                app_bundle_qs.exists()
+                app_bundle_list.append(app_bundle)
+            return response.json(0, app_bundle_list)
+        except Exception as e:
+            return response.json(500, e)
+
+    @staticmethod
+    def add_app_device_type(request_dict, response):
+        # 添加APP设备类型
+        app_bundle_name = request_dict.get('appbundleName', None)
+        app_bundle_id = request_dict.get(
+            'app_bundle_id', '')[
+                     1:-1].split(',')  # '[1,2]' -> ['1','2']
+        # app_device_type表数据
+        model = request_dict.get('model', None)
+        type = request_dict.get('type', None)
+        icon = request_dict.get('icon', None)
+        # device_name_language表数据
+        lang = request_dict.get('lang', None)
+        name = request_dict.get('name', None)
+        sort = request_dict.get('sort', None)
+
+        if not all([model, type, icon, lang, name, sort]):
+            return response.json(444)
+        type = int(type)
+
+        try:
+            with transaction.atomic():
+                for app_id in app_bundle_id:
+                    app_bundle_qs = AppBundle.objects.filter(id=app_id).values('id')
+                    if not app_bundle_qs.exists():
+                        AppBundle.objects.create(app_bundle_id=app_bundle_name, id=app_id)
+                        return response.json(0)
+                app_device_type_qs = AppDeviceType.objects.create(model=model, type=type, icon=icon)
+                DeviceNameLanguage.objects.create(lang=lang, name=name, sort=sort,
+                                                  app_device_type_id=app_device_type_qs.id)
+                for app_id in app_bundle_id:
+                    app_bundle_qs = AppBundle.objects.filter(id=app_id).values('id')
+                    app_bundle_qs = app_bundle_qs[0]['id']
+                    app_device_type_qs.appbundle_set.add(app_bundle_qs)
+            return response.json(0)
+        except Exception as e:
+            print(e)
+            return response.json(500, repr(e))
+
     @staticmethod
     def get_device_info_list(request_dict, response):
         pageNo = request_dict.get('pageNo', None)
@@ -380,8 +444,11 @@ class DeviceManagement(View):
 
     @staticmethod
     def get_app_device_type_list(request_dict, response):
-        app_bundle_id = request_dict.get('appBundleId', None)
+        app_bundle_id = request_dict.get('app_bundle_id', None)
         lang = request_dict.get('lang', 'cn')
+        model = request_dict.get('model', None)
+        type = request_dict.get('type', None)
+        name = request_dict.get('name', None)
 
         pageNo = request_dict.get('pageNo', None)
         pageSize = request_dict.get('pageSize', None)
@@ -391,6 +458,7 @@ class DeviceManagement(View):
 
         page = int(pageNo)
         line = int(pageSize)
+
         try:
             if not app_bundle_id:
                 app_bundle_id = 'com.ansjer.zccloud'
@@ -409,6 +477,13 @@ class DeviceManagement(View):
                 'app_device_type__devicenamelanguage__sort')
             if not app_bundle_qs.exists():
                 return response.json(0)
+            app_bundle_qs = app_bundle_qs.all()
+            if name:
+                app_bundle_qs = app_bundle_qs.filter(name=name)
+            if model:
+                app_bundle_qs = app_bundle_qs.filter(model=model)
+            if type:
+                app_bundle_qs = app_bundle_qs.filter(type=type)
             total = app_bundle_qs.count()
             app_bundle_qs = app_bundle_qs[(page - 1) * line:page * line]
             app_device_type_list = [app_bundle for app_bundle in app_bundle_qs]

+ 2 - 1
AdminController/LogManagementController.py

@@ -165,7 +165,8 @@ class LogManagementView(View):
 
         try:
             msg = eval(msg)
-            if not CommonService.req_publish_mqtt_msg(thing_name, topic_name, msg):
+            identification_code = thing_name[thing_name.rindex('_')+1:]
+            if not CommonService.req_publish_mqtt_msg(identification_code, topic_name, msg):
                 return response.json(10044)
             return response.json(0)
         except Exception as e:

+ 23 - 25
AdminController/ServeManagementController.py

@@ -538,31 +538,29 @@ class serveManagement(View):
         cdk_list = []
         sm_qs = Store_Meal.objects.filter(
             pay_type__payment='cdk_pay', bucket__mold=mold, is_show=0)
-        if sm_qs.exists:
-            rank = sm_qs[0].id
-            for i in range(int(cdk_num)):
-                nowTime = int(time.time())
-                cdk = hashlib.md5((str(uuid.uuid1()) +
-                                   str(nowTime)).encode('utf-8')).hexdigest()
-                cdk_model = CDKcontextModel(
-                    cdk=cdk,
-                    create_time=nowTime,
-                    valid_time=0,
-                    is_activate=0,
-                    is_down=0,
-                    rank_id=rank,
-                    order=order,
-                )
-                cdk_list.append(cdk_model)
-            try:
-                CDKcontextModel.objects.bulk_create(cdk_list)
-            except Exception as e:
-                print(repr(e))
-                return response.json(404, repr(e))
-            else:
-                return response.json(0)
-
-        return response.json(0)
+        if not sm_qs.exists():
+            return response.json(173)
+        rank = sm_qs[0].id
+        for i in range(int(cdk_num)):
+            nowTime = int(time.time())
+            cdk = hashlib.md5((str(uuid.uuid1()) +
+                               str(nowTime)).encode('utf-8')).hexdigest()
+            cdk_model = CDKcontextModel(
+                cdk=cdk,
+                create_time=nowTime,
+                valid_time=0,
+                is_activate=0,
+                is_down=0,
+                rank_id=rank,
+                order=order,
+            )
+            cdk_list.append(cdk_model)
+        try:
+            CDKcontextModel.objects.bulk_create(cdk_list)
+        except Exception as e:
+            return response.json(404, repr(e))
+        else:
+            return response.json(0)
 
     def deleteCdk(self, request_dict, response):
         cdk_id = request_dict.get("id", None)

+ 6 - 0
Ansjer/Config/__init__.py

@@ -0,0 +1,6 @@
+# -*- coding: utf-8 -*-
+"""
+@Author : Rocky
+@Time : 2022/8/8 11:24
+@File :__init__.py
+"""

+ 57 - 0
Ansjer/Config/gatewaySensorConfig.py

@@ -0,0 +1,57 @@
+# -*- coding: utf-8 -*-
+"""
+@Author : Rocky
+@Time : 2022/8/8 11:20
+@File :gatewaySensorConfig.py
+"""
+
+# MQTT主题名
+SMART_SCENE_TOPIC = 'loocam/gateway_sensor/smart_scene/{}'
+GET_SCENE_TOPIC = 'loocam/gateway_sensor/get_scene/{}'
+
+# 传感器类型
+SENSOR_TYPE = {
+    'door_magnet': 215,
+    'smart_button': 216,
+    'water_flood_sensor': 217,
+    'smoke_sensor': 218,
+    'body_sensor': 219,
+    'tem_hum_sensor': 220,
+}
+
+# 事件类型
+EVENT_TYPE = {
+    # 门磁
+    'door_magnet_opening': 2150,
+    'door_magnet_closure': 2151,
+    'door_magnet_removal': 2152,
+    'door_magnet_low_power': 2153,
+    'door_magnet_start_detection': 2154,
+    'door_magnet_closure_detection': 2155,
+    # 智能按钮
+    'smart_button_press': 2160,
+    'smart_button_click': 2161,
+    'smart_button_double_click': 2162,
+    'smart_button_three_click': 2163,
+    'smart_button_low_power': 2164,
+    # 水浸
+    'flood_trigger': 2170,
+    'flood_recovery': 2171,
+    'flood_low_power': 2172,
+    # 烟雾
+    'smoke_trigger': 2180,
+    'smoke_recovery': 2181,
+    'smoke_removal': 2182,
+    'smoke_low_power': 2183,
+    # 人体红外
+    'someone_moves': 2190,
+    'no_one_moves': 2191,
+    'body_sensor_removal': 2192,
+    'body_sensor_low_power': 2193,
+    'body_sensor_start_detection': 2194,
+    'body_sensor_closure_detection': 2195,
+    # 温湿度
+    'temperature': 2200,
+    'humidity': 2201,
+    'tem_hum_sensor_low_power': 2202,
+}

+ 1 - 0
Ansjer/config.py

@@ -82,6 +82,7 @@ AWS_ACCESS_KEY_ID = ['AKIA2MMWBR4DSFG67DTG','AKIA2E67UIMD45Y3HL53']  #0国内,
 AWS_SECRET_ACCESS_KEY = ['aI9gxcAKPmiGgPy9axrtFKzjYGbvpuytEX4xWweL','ckYLg4Lo9ZXJIcJEAKkzf2rWvs8Xth1FCjqiAqUw']
 AWS_ARN = ['arn:aws-cn:s3','arn:aws:s3']
 
+
 #尚云服务器CRCKey
 CRCKey = {'AUS':'CRCKey', 'ACN':'CRCKey'}   #{平台名:CRCKey值}
 

+ 2 - 1
Ansjer/server_urls/loocam_url.py

@@ -9,7 +9,7 @@
 from django.urls import re_path
 
 from Controller.SensorGateway import GatewayFamilyRoomController, SubDeviceController, GatewayFamilyMemberController, \
-    EquipmentFamilyController, GatewayDeviceController
+    EquipmentFamilyController, GatewayDeviceController, SmartSceneController
 
 urlpatterns = [
     re_path(r'^sensor/gateway/(?P<operation>.*)$', EquipmentFamilyController.EquipmentFamilyView.as_view()),
@@ -18,4 +18,5 @@ urlpatterns = [
             GatewayFamilyMemberController.GatewayFamilyMemberView.as_view()),
     re_path(r'^gateway/subdevice/(?P<operation>.*)$', SubDeviceController.GatewaySubDeviceView.as_view()),
     re_path(r'^gateway/device/info/(?P<operation>.*)$', GatewayDeviceController.GatewayDeviceView.as_view()),
+    re_path(r'^smartscene/(?P<operation>.*)$', SmartSceneController.SmartSceneView.as_view()),
 ]

+ 21 - 0
Ansjer/urls.py

@@ -410,3 +410,24 @@ urlpatterns = [
     re_path('(?P<path>.*)', LogManager.errorPath),
 
 ]
+
+#                                _(\_/)
+#                              ,((((^`\
+#                             ((((  (6 \
+#                           ,((((( ,    \
+#       ,,,_              ,(((((  /"._  ,`,
+#      ((((\\ ,...       ,((((   /    `-.-'
+#      )))  ;'    `"'"'""((((   (
+#     (((  /            (((      \
+#      )) |                      |
+#     ((  |        .       '     |
+#     ))  \     _ '      `t   ,.')
+#     (   |   y;- -,-""'"-.\   \/
+#     )   / ./  ) /         `\  \
+#        |./   ( (           / /'
+#        ||     \\          //'|
+#        ||      \\       _//'||
+#        ||       ))     |_/  ||
+#        \_\     |_/          ||
+#        `'"                  \_\
+#                             `'"

+ 2 - 2
Controller/AiController.py

@@ -369,8 +369,8 @@ class AiView(View):
             device_info_qs = Device_Info.objects.filter(UID=uid).values('serial_number', 'Type')
             serial_number = device_info_qs[0]['serial_number']
             device_type = device_info_qs[0]['Type']
-            if serial_number and device_type == 101:
-                ai_service_data['uid'] = CommonService.get_full_serial_number(uid, serial_number, device_type)
+            if serial_number:
+                ai_service_data['serial_number'] = CommonService.get_full_serial_number(uid, serial_number, device_type)
 
             ai_service_data['endTime'] = sum_end_time
             return response.json(0, [ai_service_data])

+ 9 - 7
Controller/CloudStorage.py

@@ -743,7 +743,7 @@ class CloudStorageView(View):
                     device_info_qs = Device_Info.objects.filter(UID=UID).values('serial_number', 'Type')
                     serial_number = device_info_qs[0]['serial_number']
                     device_type = device_info_qs[0]['Type']
-                    if serial_number and device_type == 101:
+                    if serial_number:
                         device_name = CommonService.get_full_serial_number(UID, serial_number, device_type)
                     else:
                         device_name = UID
@@ -898,7 +898,7 @@ class CloudStorageView(View):
                 device_info_qs = Device_Info.objects.filter(UID=UID).values('serial_number', 'Type')
                 serial_number = device_info_qs[0]['serial_number']
                 device_type = device_info_qs[0]['Type']
-                if serial_number and device_type == 101:
+                if serial_number:
                     device_name = CommonService.get_full_serial_number(UID, serial_number, device_type)
                 else:
                     device_name = UID
@@ -1033,7 +1033,7 @@ class CloudStorageView(View):
                     device_info_qs = Device_Info.objects.filter(UID=UID).values('serial_number', 'Type')
                     serial_number = device_info_qs[0]['serial_number']
                     device_type = device_info_qs[0]['Type']
-                    if serial_number and device_type == 101:
+                    if serial_number:
                         device_name = CommonService.get_full_serial_number(UID, serial_number, device_type)
                     else:
                         device_name = UID
@@ -1284,6 +1284,7 @@ class CloudStorageView(View):
         redisObj = RedisObject()
         isLock = redisObj.CONN.setnx(uid+'do_experience_order', 1)
         redisObj.CONN.expire(uid+'do_experience_order', 60)
+        logger = logging.getLogger('info')
         if not isLock:
             return response.json(5)
 
@@ -1387,7 +1388,7 @@ class CloudStorageView(View):
                 device_info_qs = Device_Info.objects.filter(UID=uid).values('serial_number', 'Type')
                 serial_number = device_info_qs[0]['serial_number']
                 device_type = device_info_qs[0]['Type']
-                if serial_number and device_type == 101:
+                if serial_number:
                     device_name = CommonService.get_full_serial_number(uid, serial_number, device_type)
                 else:
                     device_name = uid
@@ -1423,7 +1424,8 @@ class CloudStorageView(View):
                 result = returnurl
                 redisObj.del_data(key=uid+'do_experience_order')
                 return response.json(0, result)
-        except Exception:
+        except Exception as e:
+            logger.info('出错了~体验云存异常,errLine:{}, errMsg:{}'.format(e.__traceback__.tb_lineno, repr(e)))
             redisObj.del_data(key=uid + 'do_experience_order')
             return response.json(474)
         # red_url =
@@ -1489,7 +1491,7 @@ class CloudStorageView(View):
         device_id = uid
         serial_number = dv_qs[0]['serial_number']
         device_type = dv_qs[0]['Type']
-        if serial_number and device_type == 101:
+        if serial_number:
             device_id = CommonService.get_full_serial_number(uid, serial_number, device_type)
 
         uid_bucket[0]['uid'] = device_id
@@ -1638,7 +1640,7 @@ class CloudStorageView(View):
                     device_info_qs = Device_Info.objects.filter(UID=uid).values('serial_number', 'Type')
                     serial_number = device_info_qs[0]['serial_number']
                     device_type = device_info_qs[0]['Type']
-                    if serial_number and device_type == 101:
+                    if serial_number:
                         device_name = CommonService.get_full_serial_number(uid, serial_number, device_type)
                     else:
                         device_name = uid

+ 1 - 53
Controller/Cloudsum.py

@@ -8,7 +8,7 @@
 import json
 
 from Ansjer.config import SERVER_TYPE
-from Model.models import Order_Model, UID_Bucket, UserExModel, EquipmentLogModel
+from Model.models import Order_Model, UID_Bucket, UserExModel
 from Object.RedisObject import RedisObject
 from Object.ResponseObject import ResponseObject
 from Object.TokenObject import TokenObject
@@ -52,8 +52,6 @@ class Cloudsum(View):
             return self.usercount(userID, request_dict, response)
         if operation == 'usercloud':
             return self.usercloud(userID, response)
-        if operation == 'equipment_logs':
-            return self.equipment_logs(userID, request_dict, response)
 
     # 类型:用户手机
     # 统计用户手机型号  已有
@@ -128,53 +126,3 @@ class Cloudsum(View):
         a = Order_Model.objects.extra(select={'dates': "FROM_UNIXTIME(addTime,'%%Y-%%m')"}).values(
             'dates').filter(status=1).annotate(开通云存合计=Count('addTime')).order_by('dates')
         return response.json(0, list(a))
-
-    def equipment_logs(self, userID, request_dict, response):
-        page = int(request_dict.get('page', None))
-        line = int(request_dict.get('line', None))
-        order = request_dict.get('order', '-id')
-        if order == '':
-            order = '-id'
-        if not page or not line:
-            return response.json(444, 'page,line')
-
-        own_perm = ModelService.check_perm(userID=userID, permID=30)
-        if own_perm is not True:
-            return response.json(404)
-
-        if SERVER_TYPE == 'Ansjer.formal_settings':
-            logKey = 'logger'
-        else:
-            logKey = 'test_logger'
-        # 判断redis列表长度
-        redisObj = RedisObject()
-        data_list = redisObj.lrange(logKey, 0, -1)
-        redisObj.del_data(key=logKey)
-        add_batch_log(data_list)
-
-        qs = EquipmentLogModel.objects.all().order_by(order)
-        if qs.exists():
-            count = qs.count()
-            res = qs[(page - 1) * line:page * line]
-            send_json = CommonService.qs_to_dict(res)
-            send_json['count'] = count
-            return response.json(0, send_json)
-        return response.json(0, {'datas': [], 'count': 0})
-
-# 访问日志批量添加
-def add_batch_log(data_list):
-    try:
-        if data_list:
-            querysetlist = []
-            for i in data_list:
-                data = json.loads(i.decode('utf-8'))
-                querysetlist.append(EquipmentLogModel(**data))
-            EquipmentLogModel.objects.bulk_create(querysetlist)
-        else:
-            return
-    except Exception as e:
-        print('ggga')
-        print(repr(e))
-        return False
-    else:
-        return True

+ 78 - 75
Controller/DetectController.py

@@ -88,83 +88,86 @@ class DetectControllerView(View):
         #     qs = qs.filter(eventTime__range=(startTime, endTime))
         # if eventType:
         #     qs = qs.filter(eventType=eventType)
-        if startTime and endTime:
-            qs, count = EquipmentInfoService.find_by_start_time_equipment_info(page, line, userID, startTime,
-                                                                               endTime, eventType,
-                                                                               request_dict.get('uids', None))
+        try:
+            if startTime and endTime:
+                qs, count = EquipmentInfoService.find_by_start_time_equipment_info(page, line, userID, startTime,
+                                                                                   endTime, eventType,
+                                                                                   request_dict.get('uids', None))
 
-        else:
-            # 默认查询近七天消息推送
-            qs, count = EquipmentInfoService.get_equipment_info_week_all(page, line, userID, startTime, endTime,
-                                                                         eventType,
-                                                                         request_dict.get('uids', None))
-        logger.info('<<<|||分表查询结果count:{}'.format(count))
-        uids = request_dict.get('uids', None)
-        if uids:
-            uid_list = uids.split(',')
-            # qs = qs.filter(devUid__in=uid_list)
-            dvqs = Device_Info.objects.filter(UID__in=uid_list, userID_id=userID).values('UID', 'Type', 'NickName')
-            uid_type_dict = {}
-            for dv in dvqs:
-                uid_type_dict[dv['UID']] = {'type': dv['Type'], 'NickName': dv['NickName']}
-        else:
-            dvqs = Device_Info.objects.filter(userID_id=userID).values('UID', 'Type', 'NickName')
-            uid_type_dict = {}
-            for dv in dvqs:
-                uid_type_dict[dv['UID']] = {'type': dv['Type'], 'NickName': dv['NickName']}
-        # print(uid_type_dict)
-        if not qs or count == 0 or not qs.exists():
-            return response.json(0, {'datas': [], 'count': 0})
-        # if not qs.exists():
-        #     return response.json(0, {'datas': [], 'count': 0})
-        # qs = qs.values('id', 'devUid', 'devNickName', 'Channel', 'eventType', 'status', 'alarm', 'eventTime',
-        #                'receiveTime', 'is_st', 'addTime')
-
-        # count = qs.count()
-        # qr = qs[(page - 1) * line:page * line]
-        qr = qs
-        res = []
-        auth = oss2.Auth(OSS_STS_ACCESS_KEY, OSS_STS_ACCESS_SECRET)
-        img_bucket = oss2.Bucket(auth, 'oss-cn-shenzhen.aliyuncs.com', 'apg')
-        # vod_time_list = []
-        for p in qr:
-            devUid = p['devUid']
-            eventTime = p['eventTime']
-            channel = p['Channel']
-            if p['is_st'] == 1:
-                p['img'] = img_bucket.sign_url('GET', '{uid}/{channel}/{time}.jpeg'.
-                                               format(uid=devUid, channel=p['Channel'], time=eventTime), 300)
-                p['img_list'] = [img_bucket.sign_url('GET', '{uid}/{channel}/{time}.jpeg'.
-                                                     format(uid=devUid, channel=channel, time=eventTime), 300)]
-            elif p['is_st'] == 2:
-                # 列表装载回放时间戳标记
-                vodqs = VodHlsModel.objects.filter(uid=devUid, channel=channel, time=int(eventTime)) \
-                    .values("bucket__bucket", "bucket__endpoint")
-                # print(vodqs)
-                if vodqs.exists():
-                    bucket_name = vodqs[0]['bucket__bucket']
-                    endpoint = vodqs[0]['bucket__endpoint']
-                    bucket = oss2.Bucket(auth, endpoint, bucket_name)
-                    ts = '{uid}/vod{channel}/{etime}/ts0.ts'.format(uid=devUid, channel=p['Channel'], etime=eventTime)
-                    thumb0 = bucket.sign_url('GET', ts, 3600, params={'x-oss-process': 'video/snapshot,t_0000,w_700'})
-                    thumb1 = bucket.sign_url('GET', ts, 3600, params={'x-oss-process': 'video/snapshot,t_1000,w_700'})
-                    thumb2 = bucket.sign_url('GET', ts, 3600, params={'x-oss-process': 'video/snapshot,t_2000,w_700'})
-                    # thumb3 = bucket.sign_url('GET', ts, 3600, params={'x-oss-process': 'video/snapshot,t_3000,w_700'})
-                    p['img_list'] = [thumb0, thumb1, thumb2]
-            elif p['is_st'] == 3:
-                # 列表装载回放时间戳标记
-                p['img_list'] = []
-                for i in range(p['is_st']):
-                    img = img_bucket.sign_url('GET', '{uid}/{channel}/{time}_{st}.jpeg'.
-                                              format(uid=devUid, channel=p['Channel'], time=eventTime, st=i), 300)
-                    p['img_list'].append(img)
-            if devUid in uid_type_dict.keys():
-                p['uid_type'] = uid_type_dict[devUid]['type']
-                p['devNickName'] = uid_type_dict[devUid]['NickName']
             else:
-                p['uid_type'] = ''
-            res.append(p)
-        return response.json(0, {'datas': res, 'count': count})
+                # 默认查询近七天消息推送
+                qs, count = EquipmentInfoService.get_equipment_info_week_all(page, line, userID, startTime, endTime,
+                                                                             eventType,
+                                                                             request_dict.get('uids', None))
+            logger.info('<<<|||分表查询结果count:{}'.format(count))
+            uids = request_dict.get('uids', None)
+            if uids:
+                uid_list = uids.split(',')
+                # qs = qs.filter(devUid__in=uid_list)
+                dvqs = Device_Info.objects.filter(UID__in=uid_list, userID_id=userID).values('UID', 'Type', 'NickName')
+                uid_type_dict = {}
+                for dv in dvqs:
+                    uid_type_dict[dv['UID']] = {'type': dv['Type'], 'NickName': dv['NickName']}
+            else:
+                dvqs = Device_Info.objects.filter(userID_id=userID).values('UID', 'Type', 'NickName')
+                uid_type_dict = {}
+                for dv in dvqs:
+                    uid_type_dict[dv['UID']] = {'type': dv['Type'], 'NickName': dv['NickName']}
+            # print(uid_type_dict)
+            if not qs or count == 0 or not qs.exists():
+                return response.json(0, {'datas': [], 'count': 0})
+            # if not qs.exists():
+            #     return response.json(0, {'datas': [], 'count': 0})
+            # qs = qs.values('id', 'devUid', 'devNickName', 'Channel', 'eventType', 'status', 'alarm', 'eventTime',
+            #                'receiveTime', 'is_st', 'addTime')
+
+            # count = qs.count()
+            # qr = qs[(page - 1) * line:page * line]
+            qr = qs
+            res = []
+            auth = oss2.Auth(OSS_STS_ACCESS_KEY, OSS_STS_ACCESS_SECRET)
+            img_bucket = oss2.Bucket(auth, 'oss-cn-shenzhen.aliyuncs.com', 'apg')
+            # vod_time_list = []
+            for p in qr:
+                devUid = p['devUid']
+                eventTime = p['eventTime']
+                channel = p['Channel']
+                if p['is_st'] == 1:
+                    p['img'] = img_bucket.sign_url('GET', '{uid}/{channel}/{time}.jpeg'.
+                                                   format(uid=devUid, channel=p['Channel'], time=eventTime), 300)
+                    p['img_list'] = [img_bucket.sign_url('GET', '{uid}/{channel}/{time}.jpeg'.
+                                                         format(uid=devUid, channel=channel, time=eventTime), 300)]
+                elif p['is_st'] == 2:
+                    # 列表装载回放时间戳标记
+                    vodqs = VodHlsModel.objects.filter(uid=devUid, channel=channel, time=int(eventTime)) \
+                        .values("bucket__bucket", "bucket__endpoint")
+                    # print(vodqs)
+                    if vodqs.exists():
+                        bucket_name = vodqs[0]['bucket__bucket']
+                        endpoint = vodqs[0]['bucket__endpoint']
+                        bucket = oss2.Bucket(auth, endpoint, bucket_name)
+                        ts = '{uid}/vod{channel}/{etime}/ts0.ts'.format(uid=devUid, channel=p['Channel'], etime=eventTime)
+                        thumb0 = bucket.sign_url('GET', ts, 3600, params={'x-oss-process': 'video/snapshot,t_0000,w_700'})
+                        thumb1 = bucket.sign_url('GET', ts, 3600, params={'x-oss-process': 'video/snapshot,t_1000,w_700'})
+                        thumb2 = bucket.sign_url('GET', ts, 3600, params={'x-oss-process': 'video/snapshot,t_2000,w_700'})
+                        # thumb3 = bucket.sign_url('GET', ts, 3600, params={'x-oss-process': 'video/snapshot,t_3000,w_700'})
+                        p['img_list'] = [thumb0, thumb1, thumb2]
+                elif p['is_st'] == 3:
+                    # 列表装载回放时间戳标记
+                    p['img_list'] = []
+                    for i in range(p['is_st']):
+                        img = img_bucket.sign_url('GET', '{uid}/{channel}/{time}_{st}.jpeg'.
+                                                  format(uid=devUid, channel=p['Channel'], time=eventTime, st=i), 300)
+                        p['img_list'].append(img)
+                if devUid in uid_type_dict.keys():
+                    p['uid_type'] = uid_type_dict[devUid]['type']
+                    p['devNickName'] = uid_type_dict[devUid]['NickName']
+                else:
+                    p['uid_type'] = ''
+                res.append(p)
+            return response.json(0, {'datas': res, 'count': count})
+        except Exception as e:
+            return response.json(474)
 
     def do_change_status(self, userID, request_dict, response):
         token_val = request_dict.get('token_val', None)

+ 144 - 141
Controller/DetectControllerV2.py

@@ -300,156 +300,159 @@ class DetectControllerViewV2(View):
 
         # qs = Equipment_Info.objects.filter(userID_id=userID).order_by('-eventTime')
         # qs = qs.filter(eventTime__gt=now_time - 3600 * 168)
-        # 根据时间筛选消息推送
-        if startTime and endTime:
-            qs, count = EquipmentInfoService.find_by_start_time_equipment_info(page, line, userID, startTime,
-                                                                               endTime, eventType,
-                                                                               request_dict.get('uids', None))
+        try:
+            # 根据时间筛选消息推送
+            if startTime and endTime:
+                qs, count = EquipmentInfoService.find_by_start_time_equipment_info(page, line, userID, startTime,
+                                                                                   endTime, eventType,
+                                                                                   request_dict.get('uids', None))
 
-        else:
-            # 默认查询近七天消息推送
-            qs, count = EquipmentInfoService.get_equipment_info_week_all(page, line, userID, startTime, endTime,
-                                                                         eventType,
-                                                                         request_dict.get('uids', None))
-        # if startTime and endTime:
-        #     qs = qs.filter(eventTime__range=(startTime, endTime))
-        # if eventType:
-        #     if ',' in eventType:  # 兼容AI查询
-        #         eventTypeList = eventType.split(',')
-        #         eventTypeList = [int(i.strip()) for i in eventTypeList]
-        #         qs = qs.filter(eventType__in=eventTypeList)
-        #     else:
-        #         qs = qs.filter(eventType=eventType)
-        uids = request_dict.get('uids', None)
-        if uids:
-            uid_list = uids.split(',')
-            # qs = qs.filter(devUid__in=uid_list)
-            dvqs = Device_Info.objects.filter(UID__in=uid_list, userID_id=userID).values('UID', 'Type', 'NickName')
-            uid_type_dict = {}
-            for dv in dvqs:
-                uid_type_dict[dv['UID']] = {'type': dv['Type'], 'NickName': dv['NickName']}
-        else:
-            dvqs = Device_Info.objects.filter(userID_id=userID).values('UID', 'Type', 'NickName')
-            uid_type_dict = {}
-            for dv in dvqs:
-                uid_type_dict[dv['UID']] = {'type': dv['Type'], 'NickName': dv['NickName']}
-        # print(uid_type_dict)
-        if not qs or count == 0 or not qs.exists():
-            return response.json(0, {'datas': [], 'count': 0})
-        # qs = qs.values('id', 'devUid', 'devNickName', 'Channel', 'eventType', 'status', 'alarm', 'eventTime',
-        #                'receiveTime', 'is_st', 'addTime', 'storage_location', 'borderCoords')
-
-        # count = qs.count()
-        # qr = qs[(page - 1) * line:page * line]
-        qr = qs
-        res = []
-        auth = oss2.Auth(OSS_STS_ACCESS_KEY, OSS_STS_ACCESS_SECRET)
-        oss_img_bucket = oss2.Bucket(auth, 'oss-cn-shenzhen.aliyuncs.com', 'apg')
-        aws_s3_guonei = boto3.client(
-            's3',
-            aws_access_key_id=AWS_ACCESS_KEY_ID[0],
-            aws_secret_access_key=AWS_SECRET_ACCESS_KEY[0],
-            config=botocore.client.Config(signature_version='s3v4'),
-            region_name='cn-northwest-1'
-        )
-        aws_s3_guowai = boto3.client(
-            's3',
-            aws_access_key_id=AWS_ACCESS_KEY_ID[1],
-            aws_secret_access_key=AWS_SECRET_ACCESS_KEY[1],
-            config=botocore.client.Config(signature_version='s3v4'),
-            region_name='us-east-1'
-        )
-        # vod_time_list = []
-        # ai消息标识所有组合标签
-        ai_all_event_type = EquipmentInfoService.get_all_comb_event_type()
-        for p in qr:
-            devUid = p['devUid']
-            eventTime = p['eventTime']
-            channel = p['Channel']
-            storage_location = p['storage_location']
-            if p['is_st'] == 1:
-                thumbspng = '{uid}/{channel}/{time}.jpeg'.format(uid=devUid, channel=p['Channel'], time=eventTime)
-                if storage_location == 1:  # oss
-                    response_url = oss_img_bucket.sign_url('GET', thumbspng, 300)
-                    p['img'] = response_url
-                    p['img_list'] = [response_url]
-                elif region == 2 and storage_location == 2:  # 2:国内,aws
-                    response_url = aws_s3_guonei.generate_presigned_url('get_object',
-                                                                        Params={'Bucket': 'push', 'Key': thumbspng},
-                                                                        ExpiresIn=300)
-                    p['img'] = response_url
-                    p['img_list'] = [response_url]
-                elif region == 1 and storage_location == 2:  # 1:国外,aws
-                    response_url = aws_s3_guowai.generate_presigned_url('get_object',
-                                                                        Params={'Bucket': 'foreignpush',
-                                                                                'Key': thumbspng},
-                                                                        ExpiresIn=300)
-                    p['img'] = response_url
-                    p['img_list'] = [response_url]
-
-            elif p['is_st'] == 2:
-                # 列表装载回放时间戳标记
-                vodqs = VodHlsModel.objects.filter(uid=devUid, channel=channel, time=int(eventTime)) \
-                    .values("bucket__bucket", "bucket__endpoint")
-                # print(vodqs)
-                if vodqs.exists():
-                    bucket_name = vodqs[0]['bucket__bucket']
-                    endpoint = vodqs[0]['bucket__endpoint']
-                    bucket = oss2.Bucket(auth, endpoint, bucket_name)
-                    ts = '{uid}/vod{channel}/{etime}/ts0.ts'.format(uid=devUid, channel=p['Channel'], etime=eventTime)
-                    if storage_location == 1:  # oss
-                        thumb0 = bucket.sign_url('GET', ts, 3600,
-                                                 params={'x-oss-process': 'video/snapshot,t_0000,w_700'})
-                        thumb1 = bucket.sign_url('GET', ts, 3600,
-                                                 params={'x-oss-process': 'video/snapshot,t_1000,w_700'})
-                        thumb2 = bucket.sign_url('GET', ts, 3600,
-                                                 params={'x-oss-process': 'video/snapshot,t_2000,w_700'})
-                        # thumb3 = bucket.sign_url('GET', ts, 3600, params={'x-oss-process': 'video/snapshot,t_3000,w_700'})
-                        p['img_list'] = [thumb0, thumb1, thumb2]
-                    elif region == 2 and storage_location == 2:  # 2:国内,aws
-                        thumb = aws_s3_guonei.generate_presigned_url('get_object',
-                                                                     Params={'Bucket': 'push', 'Key': ts},
-                                                                     ExpiresIn=3600)
-                        p['img_list'] = [thumb]
-                    elif region == 1 and storage_location == 2:  # 1:国外,aws
-                        thumb = aws_s3_guowai.generate_presigned_url('get_object',
-                                                                     Params={'Bucket': 'foreignpush', 'Key': ts},
-                                                                     ExpiresIn=3600)
-                        p['img_list'] = [thumb]
-            elif p['is_st'] == 3 or p['is_st'] == 4:
-                # 列表装载回放时间戳标记
-                p['img_list'] = []
-                for i in range(p['is_st']):
-                    thumbspng = '{uid}/{channel}/{time}_{st}.jpeg'.format(uid=devUid, channel=p['Channel'],
-                                                                          time=eventTime, st=i)
+            else:
+                # 默认查询近七天消息推送
+                qs, count = EquipmentInfoService.get_equipment_info_week_all(page, line, userID, startTime, endTime,
+                                                                             eventType,
+                                                                             request_dict.get('uids', None))
+            # if startTime and endTime:
+            #     qs = qs.filter(eventTime__range=(startTime, endTime))
+            # if eventType:
+            #     if ',' in eventType:  # 兼容AI查询
+            #         eventTypeList = eventType.split(',')
+            #         eventTypeList = [int(i.strip()) for i in eventTypeList]
+            #         qs = qs.filter(eventType__in=eventTypeList)
+            #     else:
+            #         qs = qs.filter(eventType=eventType)
+            uids = request_dict.get('uids', None)
+            if uids:
+                uid_list = uids.split(',')
+                # qs = qs.filter(devUid__in=uid_list)
+                dvqs = Device_Info.objects.filter(UID__in=uid_list, userID_id=userID).values('UID', 'Type', 'NickName')
+                uid_type_dict = {}
+                for dv in dvqs:
+                    uid_type_dict[dv['UID']] = {'type': dv['Type'], 'NickName': dv['NickName']}
+            else:
+                dvqs = Device_Info.objects.filter(userID_id=userID).values('UID', 'Type', 'NickName')
+                uid_type_dict = {}
+                for dv in dvqs:
+                    uid_type_dict[dv['UID']] = {'type': dv['Type'], 'NickName': dv['NickName']}
+            # print(uid_type_dict)
+            if not qs or count == 0 or not qs.exists():
+                return response.json(0, {'datas': [], 'count': 0})
+            # qs = qs.values('id', 'devUid', 'devNickName', 'Channel', 'eventType', 'status', 'alarm', 'eventTime',
+            #                'receiveTime', 'is_st', 'addTime', 'storage_location', 'borderCoords')
+
+            # count = qs.count()
+            # qr = qs[(page - 1) * line:page * line]
+            qr = qs
+            res = []
+            auth = oss2.Auth(OSS_STS_ACCESS_KEY, OSS_STS_ACCESS_SECRET)
+            oss_img_bucket = oss2.Bucket(auth, 'oss-cn-shenzhen.aliyuncs.com', 'apg')
+            aws_s3_guonei = boto3.client(
+                's3',
+                aws_access_key_id=AWS_ACCESS_KEY_ID[0],
+                aws_secret_access_key=AWS_SECRET_ACCESS_KEY[0],
+                config=botocore.client.Config(signature_version='s3v4'),
+                region_name='cn-northwest-1'
+            )
+            aws_s3_guowai = boto3.client(
+                's3',
+                aws_access_key_id=AWS_ACCESS_KEY_ID[1],
+                aws_secret_access_key=AWS_SECRET_ACCESS_KEY[1],
+                config=botocore.client.Config(signature_version='s3v4'),
+                region_name='us-east-1'
+            )
+            # vod_time_list = []
+            # ai消息标识所有组合标签
+            ai_all_event_type = EquipmentInfoService.get_all_comb_event_type()
+            for p in qr:
+                devUid = p['devUid']
+                eventTime = p['eventTime']
+                channel = p['Channel']
+                storage_location = p['storage_location']
+                if p['is_st'] == 1:
+                    thumbspng = '{uid}/{channel}/{time}.jpeg'.format(uid=devUid, channel=p['Channel'], time=eventTime)
                     if storage_location == 1:  # oss
-                        img = oss_img_bucket.sign_url('GET', thumbspng, 300)
-                        p['img_list'].append(img)
-                    elif region == 2 and storage_location == 2:  # 2:国内,aws
+                        response_url = oss_img_bucket.sign_url('GET', thumbspng, 300)
+                        p['img'] = response_url
+                        p['img_list'] = [response_url]
+                    elif region == 2 and storage_location == 2:  # 2:国内,aws
                         response_url = aws_s3_guonei.generate_presigned_url('get_object',
                                                                             Params={'Bucket': 'push', 'Key': thumbspng},
                                                                             ExpiresIn=300)
-                        img = response_url
-                        p['img_list'].append(img)
-                    elif region == 1 and storage_location == 2:  # 1:国外,aws
+                        p['img'] = response_url
+                        p['img_list'] = [response_url]
+                    elif region == 1 and storage_location == 2:  # 1:国外,aws
                         response_url = aws_s3_guowai.generate_presigned_url('get_object',
                                                                             Params={'Bucket': 'foreignpush',
                                                                                     'Key': thumbspng},
                                                                             ExpiresIn=300)
-                        img = response_url
-                        p['img_list'].append(img)
-            if devUid in uid_type_dict.keys():
-                p['uid_type'] = uid_type_dict[devUid]['type']
-                p['devNickName'] = uid_type_dict[devUid]['NickName']
-            else:
-                p['uid_type'] = ''
-
-            p['borderCoords'] = '' if p['borderCoords'] == '' else json.loads(p['borderCoords'])  # ai消息坐标信息
-            p['ai_event_type_list'] = []
-            if p['eventType'] in ai_all_event_type:  # 如果是ai消息类型,则分解eventType, 如:123 -> [1,2,3]
-                p['ai_event_type_list'] = list(map(int, str(p['eventType'])))
-            res.append(p)
-        return response.json(0, {'datas': res, 'count': count})
+                        p['img'] = response_url
+                        p['img_list'] = [response_url]
+
+                elif p['is_st'] == 2:
+                    # 列表装载回放时间戳标记
+                    vodqs = VodHlsModel.objects.filter(uid=devUid, channel=channel, time=int(eventTime)) \
+                        .values("bucket__bucket", "bucket__endpoint")
+                    # print(vodqs)
+                    if vodqs.exists():
+                        bucket_name = vodqs[0]['bucket__bucket']
+                        endpoint = vodqs[0]['bucket__endpoint']
+                        bucket = oss2.Bucket(auth, endpoint, bucket_name)
+                        ts = '{uid}/vod{channel}/{etime}/ts0.ts'.format(uid=devUid, channel=p['Channel'], etime=eventTime)
+                        if storage_location == 1:  # oss
+                            thumb0 = bucket.sign_url('GET', ts, 3600,
+                                                     params={'x-oss-process': 'video/snapshot,t_0000,w_700'})
+                            thumb1 = bucket.sign_url('GET', ts, 3600,
+                                                     params={'x-oss-process': 'video/snapshot,t_1000,w_700'})
+                            thumb2 = bucket.sign_url('GET', ts, 3600,
+                                                     params={'x-oss-process': 'video/snapshot,t_2000,w_700'})
+                            # thumb3 = bucket.sign_url('GET', ts, 3600, params={'x-oss-process': 'video/snapshot,t_3000,w_700'})
+                            p['img_list'] = [thumb0, thumb1, thumb2]
+                        elif region == 2 and storage_location == 2:  # 2:国内,aws
+                            thumb = aws_s3_guonei.generate_presigned_url('get_object',
+                                                                         Params={'Bucket': 'push', 'Key': ts},
+                                                                         ExpiresIn=3600)
+                            p['img_list'] = [thumb]
+                        elif region == 1 and storage_location == 2:  # 1:国外,aws
+                            thumb = aws_s3_guowai.generate_presigned_url('get_object',
+                                                                         Params={'Bucket': 'foreignpush', 'Key': ts},
+                                                                         ExpiresIn=3600)
+                            p['img_list'] = [thumb]
+                elif p['is_st'] == 3 or p['is_st'] == 4:
+                    # 列表装载回放时间戳标记
+                    p['img_list'] = []
+                    for i in range(p['is_st']):
+                        thumbspng = '{uid}/{channel}/{time}_{st}.jpeg'.format(uid=devUid, channel=p['Channel'],
+                                                                              time=eventTime, st=i)
+                        if storage_location == 1:  # oss
+                            img = oss_img_bucket.sign_url('GET', thumbspng, 300)
+                            p['img_list'].append(img)
+                        elif region == 2 and storage_location == 2:  # 2:国内,aws
+                            response_url = aws_s3_guonei.generate_presigned_url('get_object',
+                                                                                Params={'Bucket': 'push', 'Key': thumbspng},
+                                                                                ExpiresIn=300)
+                            img = response_url
+                            p['img_list'].append(img)
+                        elif region == 1 and storage_location == 2:  # 1:国外,aws
+                            response_url = aws_s3_guowai.generate_presigned_url('get_object',
+                                                                                Params={'Bucket': 'foreignpush',
+                                                                                        'Key': thumbspng},
+                                                                                ExpiresIn=300)
+                            img = response_url
+                            p['img_list'].append(img)
+                if devUid in uid_type_dict.keys():
+                    p['uid_type'] = uid_type_dict[devUid]['type']
+                    p['devNickName'] = uid_type_dict[devUid]['NickName']
+                else:
+                    p['uid_type'] = ''
+
+                p['borderCoords'] = '' if p['borderCoords'] == '' else json.loads(p['borderCoords'])  # ai消息坐标信息
+                p['ai_event_type_list'] = []
+                if p['eventType'] in ai_all_event_type:  # 如果是ai消息类型,则分解eventType, 如:123 -> [1,2,3]
+                    p['ai_event_type_list'] = list(map(int, str(p['eventType'])))
+                res.append(p)
+            return response.json(0, {'datas': res, 'count': count})
+        except Exception as e:
+            return response.json(474)
 
     def do_update_interval(self, userID, request_dict, response):
         uid = request_dict.get('uid', None)

+ 12 - 3
Controller/DeviceShare.py

@@ -24,6 +24,7 @@ from Object.RedisObject import RedisObject
 from Object.ResponseObject import ResponseObject
 from Object.TokenObject import TokenObject
 from Service.CommonService import CommonService
+from Controller.SensorGateway.EquipmentFamilyController import EquipmentFamilyView
 
 
 class DeviceShareView(View):
@@ -141,16 +142,21 @@ class DeviceShareView(View):
 
     def do_confirm(self, userID, request_dict, response):
         shareToken = request_dict.get('shareToken', None)
-        if shareToken is not None:
+        family_id = request_dict.get('familyId', None)
+        room_id = request_dict.get('roomId', None)
+        if not shareToken:
+            return response.json(444, {'param': 'shareToken'})
             # try:
             #     data = jwt.decode(shareToken, '.#^^&', algorithms='HS256')
             # except Exception as e:
             #     return response.json(10, repr(e))
+        try:
             redisObj = RedisObject()
             data_str = redisObj.get_data(key=shareToken)
             if not data_str:
                 return response.json(119)
             data = json.loads(data_str)
+            print('data:', data)
             # 分享者userID
             sharer = data.get('sharer', None)
             # 分享的uid
@@ -177,6 +183,7 @@ class DeviceShareView(View):
                     sharerDvqs.primaryMaster = primaryMaster
                     sharerDvqs.data_joined = None
                     sharerDvqs.save()
+
                     # redisObj = RedisObject(db=8)
                     # redisObj.del_data(key='uid_qs_' + userID)
                 except Exception as e:
@@ -189,6 +196,8 @@ class DeviceShareView(View):
                                                                           'primaryUserID', 'primaryMaster',
                                                                           'data_joined', 'version',
                                                                           'isVod', 'isExist')
+                    if family_id:
+                        EquipmentFamilyView.family_room_device_save(family_id, room_id, deviceId, dvqs[0]['Type'])
                     dvql = CommonService.qs_to_list(dvqs)
                     ubqs = UID_Bucket.objects.filter(uid=UID). \
                         values('bucket__content', 'status', 'channel', 'endTime', 'uid')
@@ -198,8 +207,8 @@ class DeviceShareView(View):
                     return response.json(0, res)
             else:
                 return response.json(174)
-        else:
-            return response.json(444, {'param': 'shareToken'})
+        except Exception as e:
+            return response.json(500, repr(e))
 
     # 1,这个用户的分享出去的设备
     # 2,获得上面个的设备拥有者

+ 60 - 36
Controller/EquipmentManager.py

@@ -8,7 +8,7 @@ import requests
 import simplejson as json
 from django.utils import timezone
 from Model.models import Device_User, Device_Info, UID_Bucket, UID_Preview, UidSetModel, UidPushModel, \
-    UIDCompanySerialModel, iotdeviceInfoModel, UIDMainUser, UidChannelSetModel
+    UIDCompanySerialModel, iotdeviceInfoModel, UIDMainUser, UidChannelSetModel, LogModel
 from django.db.models import Q
 from Object.ResponseObject import ResponseObject
 from Object.TokenObject import TokenObject
@@ -796,39 +796,49 @@ def deleteInterface(request):
         return response.json(309)
     try:
         dv_qs = Device_Info.objects.filter(userID_id=userID, id=id)
-        if dv_qs.exists():
-            uid = dv_qs[0].UID
-            asy = threading.Thread(target=ModelService.delete_log,
-                                   args=(CommonService.get_ip_address(request), userID, 'deleteV2', uid))
-            asy.start()
-            if userID == dv_qs[0].vodPrimaryUserID:
-                Device_Info.objects.filter(UID=uid).update(vodPrimaryUserID='', vodPrimaryMaster='')
+        if not dv_qs.exists():
+            return response.json(14)
+        uid = dv_qs[0].UID
+        if userID == dv_qs[0].vodPrimaryUserID:
+            Device_Info.objects.filter(UID=uid).update(vodPrimaryUserID='', vodPrimaryMaster='')
 
-            if dv_qs[0].isShare:
-                dv_qs.delete()
-            else:
-                # a.主用户删除设备
-                dv_qs.delete()
-                # 删除设备影子信息uid_set   外键关联删除设备推送配置信息 uid_push
-                up_qs = UidPushModel.objects.filter(uid_set__uid=uid)
-                DetectControllerView().do_delete_redis(uid)
-                if up_qs.count() > 1:
-                    UidPushModel.objects.filter(uid_set__uid=uid, userID_id=userID).delete()
-                    redisObj = RedisObject(db=6, SERVER_HOST=PUSH_REDIS_ADDRESS)
-                    ykey = '{uid}_redis_qs'.format(uid=uid)
-                    if ykey:
-                        redisObj.del_data(key=ykey)
-                else:
-                    up_qs.delete()
-                # b.删除次用户设备
-                Device_Info.objects.filter(UID=uid, isShare=True, primaryUserID=userID).delete()
-                # 异步删除推送消息
-            asy = threading.Thread(target=ModelService.del_eq_info, args=(userID, uid))
-            asy.start()
-            # redisObj = RedisObject(db=8)
-            # redisObj.del_data(key='uid_qs_' + userID)
+        if dv_qs[0].isShare:
+            dv_qs.delete()
         else:
-            return response.json(14)
+            # a.主用户删除设备
+            dv_qs.delete()
+            # 删除设备影子信息uid_set   外键关联删除设备推送配置信息 uid_push
+            up_qs = UidPushModel.objects.filter(uid_set__uid=uid)
+            DetectControllerView().do_delete_redis(uid)
+            if up_qs.count() > 1:
+                UidPushModel.objects.filter(uid_set__uid=uid, userID_id=userID).delete()
+                redisObj = RedisObject(db=6, SERVER_HOST=PUSH_REDIS_ADDRESS)
+                ykey = '{uid}_redis_qs'.format(uid=uid)
+                if ykey:
+                    redisObj.del_data(key=ykey)
+            else:
+                up_qs.delete()
+            # b.删除次用户设备
+            Device_Info.objects.filter(UID=uid, isShare=True, primaryUserID=userID).delete()
+            # 异步删除推送消息
+        asy = threading.Thread(target=ModelService.del_eq_info, args=(userID, uid))
+        asy.start()
+
+        # 记录操作日志
+        now_time = int(time.time())
+        ip = CommonService.get_ip_address(request)
+        content = json.loads(json.dumps(request_dict))
+        log = {
+            'ip': ip,
+            'user_id': 1,
+            'status': 200,
+            'time': now_time,
+            'content': json.dumps(content),
+            'url': 'equipment/delete',
+            'operation': '{}删除设备,uid:{}'.format(userID, uid),
+        }
+        LogModel.objects.create(**log)
+
     except Exception as e:
         errorInfo = traceback.format_exc()
         print('删除数据库记录错误: %s' % errorInfo)
@@ -868,11 +878,10 @@ def batchDeleteInterface(request):
         deviceInfo_qs = Device_Info.objects.filter(userID_id=userID, id__in=ids.split(','))
         if not deviceInfo_qs.exists():
             return response.json(14)
+        uid_list = []
         for deviceInfo in deviceInfo_qs:
             uid = deviceInfo.UID
-            asy = threading.Thread(target=ModelService.delete_log,
-                                   args=(CommonService.get_ip_address(request), userID, 'deleteV2', uid))
-            asy.start()
+            uid_list.append(uid)
             if userID == deviceInfo.vodPrimaryUserID:
                 Device_Info.objects.filter(UID=uid).update(vodPrimaryUserID='', vodPrimaryMaster='')
 
@@ -892,9 +901,24 @@ def batchDeleteInterface(request):
                     up_qs.delete()
                 # b.删除次用户设备
                 Device_Info.objects.filter(UID=uid, isShare=True, primaryUserID=userID).delete()
-                    # 异步删除推送消息
+                # 异步删除推送消息
             asy = threading.Thread(target=ModelService.del_eq_info, args=(userID, uid))
             asy.start()
+
+        # 记录操作日志
+        now_time = int(time.time())
+        ip = CommonService.get_ip_address(request)
+        content = json.loads(json.dumps(request_dict))
+        log = {
+            'ip': ip,
+            'user_id': 1,
+            'status': 200,
+            'time': now_time,
+            'content': json.dumps(content),
+            'url': 'equipment/batchDelete',
+            'operation': '{}批量删除设备,uid:{}'.format(userID, uid_list),
+        }
+        LogModel.objects.create(**log)
     except Exception as e:
         errorInfo = traceback.format_exc()
         print('删除数据库记录错误: %s' % errorInfo)

+ 2 - 2
Controller/EquipmentManagerV2.py

@@ -326,8 +326,8 @@ class EquipmentManagerV2(View):
 
         for p in dvls:
             # 如果存在序列号返回完整序列号
-            if p['serial_number'] and p['Type'] == 101:
-                p['UID'] = CommonService.get_full_serial_number(p['UID'], p['serial_number'], p['Type'])
+            if p['serial_number']:
+                p['serial_number'] = CommonService.get_full_serial_number(p['UID'], p['serial_number'], p['Type'])
             # 新增IOT
             p['iot'] = []
             for iot in iotqs:

+ 57 - 51
Controller/EquipmentManagerV3.py

@@ -1,24 +1,24 @@
+import json
 import re
 import threading
 import time
-import traceback
 
+import base64
+import oss2
 import requests
-
-from Controller.CheckUserData import RandomStr
-import oss2, base64
 from django.db.models import Q
 from django.views.generic.base import View
+
+from Ansjer.config import OSS_STS_ACCESS_SECRET, OSS_STS_ACCESS_KEY
+from Controller.CheckUserData import RandomStr
 from Controller.DeviceConfirmRegion import Device_Region
-from Object.RedisObject import RedisObject
-from Ansjer.config import OSS_STS_ACCESS_SECRET, OSS_STS_ACCESS_KEY, BASE_DIR
-from Model.models import Device_Info, UID_Bucket, UID_Preview, UidSetModel, UidPushModel, UidChannelSetModel, \
-    Device_User, iotdeviceInfoModel, UIDCompanySerialModel, UIDMainUser, UIDModel, UnicomDeviceInfo
+from Controller.SensorGateway.EquipmentFamilyController import EquipmentFamilyView
+from Model.models import Device_Info, UID_Bucket, UID_Preview, UidSetModel, UidChannelSetModel, \
+    Device_User, iotdeviceInfoModel, UIDCompanySerialModel, UIDModel, UnicomDeviceInfo
 from Object.ResponseObject import ResponseObject
 from Object.TokenObject import TokenObject
 from Service.CommonService import CommonService
 from Service.ModelService import ModelService
-import time, json
 
 
 class EquipmentManagerV3(View):
@@ -61,7 +61,7 @@ class EquipmentManagerV3(View):
         elif operation == 'fuzzyQuery':
             return self.do_fuzzy_query(userID, request_dict, response)
         elif operation == 'mainUserDevice':
-            return self.do_mainUserDevice( request_dict, response)
+            return self.do_mainUserDevice(request_dict, response)
         elif operation == 'getDeviceFeatures':
             return self.do_get_device_features(request_dict, response)
         else:
@@ -79,6 +79,9 @@ class EquipmentManagerV3(View):
         version = request_dict.get('version', '')
         isCheckMainUser = request_dict.get('isCheckMainUser', None)
 
+        family_id = request_dict.get('familyId', None)
+        room_id = request_dict.get('roomId', None)
+
         if not all([UID, NickName, View_Account, Type, ChannelIndex]):  # Type和ChannelIndex可能为0
             return response.json(444, {'param': 'UID, NickName, View_Account, Type, ChannelIndex'})
 
@@ -111,19 +114,18 @@ class EquipmentManagerV3(View):
         primaryMaster = ''
         isShare = False
 
-        is_bind = Device_Info.objects.filter(UID=UID, isShare=False).values('userID__userID', 'primaryUserID', 'primaryMaster')
+        is_bind = Device_Info.objects.filter(UID=UID, isShare=False).values('userID__userID', 'primaryUserID',
+                                                                            'primaryMaster')
 
         if main_exist.exists():
             vodPrimaryUserID = main_exist[0]['vodPrimaryUserID']
             vodPrimaryMaster = main_exist[0]['vodPrimaryMaster']
 
-
         if is_bind.exists():
             primaryUserID = is_bind[0]['primaryUserID']
             primaryMaster = is_bind[0]['primaryMaster']
             isShare = True
 
-
         isusermain = False
         if (vodPrimaryUserID != userID and vodPrimaryUserID != '') or (primaryUserID != userID and primaryUserID != ''):
             isusermain = True
@@ -192,8 +194,8 @@ class EquipmentManagerV3(View):
                 # 多通道设备设置通道名
                 if Type in dvr_type_list:
                     UidChannelSet_bulk = []
-                    for i in range(1, ChannelIndex+1):
-                        channel_name = 'channel'+str(i)  # channel1,channel2...
+                    for i in range(1, ChannelIndex + 1):
+                        channel_name = 'channel' + str(i)  # channel1,channel2...
                         UidChannelSet = UidChannelSetModel(uid_id=UidSet_id, channel=i, channel_name=channel_name)
                         UidChannelSet_bulk.append(UidChannelSet)
                     UidChannelSetModel.objects.bulk_create(UidChannelSet_bulk)
@@ -202,6 +204,10 @@ class EquipmentManagerV3(View):
                                      View_Password=View_Password, Type=Type, ChannelIndex=ChannelIndex, version=version,
                                      vodPrimaryUserID=vodPrimaryUserID, vodPrimaryMaster=vodPrimaryMaster)
             userDevice.save()
+            # 添加到家庭房间
+            if family_id:
+                EquipmentFamilyView.family_room_device_save(family_id, room_id, userDevice.id, Type)
+
             uid_serial_qs = UIDCompanySerialModel.objects.filter(uid__uid=UID)
             if uid_serial_qs.exists():
                 uid_serial = uid_serial_qs[0]
@@ -220,7 +226,7 @@ class EquipmentManagerV3(View):
             if us_qs.exists() and us_qs[0].is_alexa == 1:
                 if us_qs[0].channel > 1:
                     data_list = []
-                    uid_channel_set_qs = UidChannelSetModel.objects.filter(uid_id=us_qs[0].id).\
+                    uid_channel_set_qs = UidChannelSetModel.objects.filter(uid_id=us_qs[0].id). \
                         values('channel', 'channel_name')
                     if uid_channel_set_qs.exists():
                         # 多通道设备名为 UidChannelSetModel 的 channel_name
@@ -257,15 +263,13 @@ class EquipmentManagerV3(View):
             iotqs = iotdeviceInfoModel.objects.filter(serial_number=dvql[0]['serial_number'])
             if iotqs.exists():
                 res['iot'] = {
-                        'endpoint': iotqs[0].endpoint,
-                        'token_iot_number': iotqs[0].endpoint
+                    'endpoint': iotqs[0].endpoint,
+                    'token_iot_number': iotqs[0].endpoint
                 }
 
-            # 除C1的序列号暂时返回''
-            if res['serial_number'] and Type == 101:
+            # 存在序列号返回完整序列号
+            if res['serial_number']:
                 res['serial_number'] = CommonService.get_full_serial_number(UID, res['serial_number'], Type)
-            else:
-                res['serial_number'] = ''
 
             return response.json(0, res)
 
@@ -292,16 +296,16 @@ class EquipmentManagerV3(View):
             return response.json(444, {'param': 'uidContent'})
 
         try:
-            deviceNumber = 0            # 添加成功数量
-            add_success_flag = False    # 添加成功标识
-            exception_flag = False      # 异常标识
-            exists_flag = False         # 已存在标识
+            deviceNumber = 0  # 添加成功数量
+            add_success_flag = False  # 添加成功标识
+            exception_flag = False  # 异常标识
+            exists_flag = False  # 已存在标识
             uid_content_list = eval(uidContent)
             print('uidContent: ', uid_content_list)
             re_uid = re.compile(r'^[A-Za-z0-9]{14,20}$')
             for uid_content in uid_content_list:
                 exception_flag = False  # 重置异常标识
-                exists_flag = False     # 已存在标识
+                exists_flag = False  # 已存在标识
                 UID = uid_content['uid']
                 NickName = uid_content['nickName']
                 Type = uid_content['type']
@@ -314,7 +318,7 @@ class EquipmentManagerV3(View):
                 if not all([UID, NickName, View_Account]):  # Type和ChannelIndex可能为0
                     return response.json(444, {'param': 'UID, NickName, View_Account'})
 
-                if not re_uid.match(UID):   # 检查uid长度
+                if not re_uid.match(UID):  # 检查uid长度
                     return response.json(444, {'error uid length': UID})
 
                 device_info_qs = Device_Info.objects.filter(UID=UID, userID_id=userID)
@@ -338,7 +342,8 @@ class EquipmentManagerV3(View):
                 primaryMaster = ''
                 isShare = False
 
-                is_bind = Device_Info.objects.filter(UID=UID, isShare=False).values('userID__userID', 'primaryUserID', 'primaryMaster')
+                is_bind = Device_Info.objects.filter(UID=UID, isShare=False).values('userID__userID', 'primaryUserID',
+                                                                                    'primaryMaster')
 
                 if main_exist.exists():
                     vodPrimaryUserID = main_exist[0]['vodPrimaryUserID']
@@ -350,7 +355,8 @@ class EquipmentManagerV3(View):
                     isShare = True
 
                 isusermain = False
-                if (vodPrimaryUserID != userID and vodPrimaryUserID != '') or (primaryUserID != userID and primaryUserID != ''):
+                if (vodPrimaryUserID != userID and vodPrimaryUserID != '') or (
+                        primaryUserID != userID and primaryUserID != ''):
                     isusermain = True
 
                 # 判断是否有已绑定用户
@@ -417,14 +423,15 @@ class EquipmentManagerV3(View):
                     multi_channel_list = [1, 2, 3, 4, 10001]
                     if Type in multi_channel_list:
                         UidChannelSet_bulk = []
-                        for i in range(1, ChannelIndex+1):
-                            channel_name = 'channel'+str(i)  # channel1,channel2...
+                        for i in range(1, ChannelIndex + 1):
+                            channel_name = 'channel' + str(i)  # channel1,channel2...
                             UidChannelSet = UidChannelSetModel(uid_id=UidSet_id, channel=i, channel_name=channel_name)
                             UidChannelSet_bulk.append(UidChannelSet)
                         UidChannelSetModel.objects.bulk_create(UidChannelSet_bulk)
 
                 userDevice = Device_Info(id=id, userID_id=userID, UID=UID, NickName=NickName, View_Account=View_Account,
-                                         View_Password=View_Password, Type=Type, ChannelIndex=ChannelIndex, version=version,
+                                         View_Password=View_Password, Type=Type, ChannelIndex=ChannelIndex,
+                                         version=version,
                                          vodPrimaryUserID=vodPrimaryUserID, vodPrimaryMaster=vodPrimaryMaster)
                 userDevice.save()
                 uid_serial_qs = UIDCompanySerialModel.objects.filter(uid__uid=UID)
@@ -443,13 +450,14 @@ class EquipmentManagerV3(View):
                 if us_qs.exists() and us_qs[0].is_alexa == 1:
                     if us_qs[0].channel > 1:
                         data_list = []
-                        uid_channel_set_qs = UidChannelSetModel.objects.filter(uid_id=us_qs[0].id).\
+                        uid_channel_set_qs = UidChannelSetModel.objects.filter(uid_id=us_qs[0].id). \
                             values('channel', 'channel_name')
                         if uid_channel_set_qs.exists():
                             # 多通道设备名为 UidChannelSetModel 的 channel_name
                             for uid_channel_set in uid_channel_set_qs:
-                                data_list.append({'userID': userID, 'UID': UID, 'uid_nick': uid_channel_set['channel_name'],
-                                                  'channel': uid_channel_set['channel'], 'password': encryptPassword})
+                                data_list.append(
+                                    {'userID': userID, 'UID': UID, 'uid_nick': uid_channel_set['channel_name'],
+                                     'channel': uid_channel_set['channel'], 'password': encryptPassword})
                     else:
                         data_list = [{'userID': userID, 'UID': UID, 'uid_nick': NickName, 'password': encryptPassword}]
 
@@ -466,7 +474,8 @@ class EquipmentManagerV3(View):
                                                                 'vodPrimaryUserID', 'vodPrimaryMaster',
                                                                 'userID__userEmail',
                                                                 'data_joined', 'version',
-                                                                'isVod', 'isExist', 'isCameraOpenCloud', 'serial_number')
+                                                                'isVod', 'isExist', 'isCameraOpenCloud',
+                                                                'serial_number')
                 dvql = CommonService.qs_to_list(dvqs)
                 ubqs = UID_Bucket.objects.filter(uid=UID). \
                     values('bucket__content', 'status', 'channel', 'endTime', 'uid')
@@ -484,9 +493,9 @@ class EquipmentManagerV3(View):
             exception_flag = True
             pass
         finally:
-            if add_success_flag:    # 有一台添加成功则返回成功
+            if add_success_flag:  # 有一台添加成功则返回成功
                 return response.json(0, success_res)
-            if exists_flag:         # 全部设备已存在
+            if exists_flag:  # 全部设备已存在
                 return response.json(174, exists_res)
             if exception_flag:
                 return response.json(500, error_res)
@@ -596,7 +605,7 @@ class EquipmentManagerV3(View):
         dvqs = Device_Info.objects.filter(userID_id=userID)
         # # 过滤已重置的设备
         dvqs = dvqs.filter(~Q(isExist=2))
-        dvql = dvqs.values('id', 'userID', 'NickName', 'UID', 'View_Account','View_Password', 'ChannelIndex',
+        dvql = dvqs.values('id', 'userID', 'NickName', 'UID', 'View_Account', 'View_Password', 'ChannelIndex',
                            'Type', 'isShare', 'primaryUserID', 'primaryMaster', 'data_joined', 'vodPrimaryUserID',
                            'vodPrimaryMaster', 'userID__userEmail', 'version', 'isVod', 'isExist', 'NotificationMode',
                            'isCameraOpenCloud', 'serial_number')
@@ -698,7 +707,7 @@ class EquipmentManagerV3(View):
             p['iot'] = []
             if p['serial_number']:  # 存在序列号根据序列号查询
                 iotdeviceInfo_qs = iotdeviceInfoModel.objects.filter(serial_number=p['serial_number'][0:6])
-            else:   # 根据uid查询
+            else:  # 根据uid查询
                 iotdeviceInfo_qs = iotdeviceInfoModel.objects.filter(uid=p['UID'])
             if iotdeviceInfo_qs.exists():
                 iotdeviceInfo = iotdeviceInfo_qs.values('endpoint', 'token_iot_number')
@@ -706,9 +715,7 @@ class EquipmentManagerV3(View):
                     'endpoint': iotdeviceInfo[0]['endpoint'],
                     'token_iot_number': iotdeviceInfo[0]['token_iot_number']
                 })
-            # C1返回序列号
-            if p['Type'] != 101:
-                p['serial_number'] = ''
+
             p['vod'] = []
             for dm in ubqs:
                 if p['UID'] == dm['uid']:
@@ -733,8 +740,8 @@ class EquipmentManagerV3(View):
             if p_uid in uv_dict:
                 # 设备版本号
                 uidversion = uv_dict[p_uid]['version']
-                if len(uidversion) >6:
-                    uidversion = uidversion[0 : uidversion.rfind('.')]
+                if len(uidversion) > 6:
+                    uidversion = uidversion[0: uidversion.rfind('.')]
                 p['uid_version'] = uidversion
                 p['ucode'] = uv_dict[p_uid]['ucode']
                 p['detect_interval'] = uv_dict[p_uid]['detect_interval']
@@ -1011,16 +1018,15 @@ class EquipmentManagerV3(View):
             phone = qs[0]['phone']
             username = qs[0]['username']
             qs = CommonService.qs_to_list(qs)
-            if NickName =='':
+            if NickName == '':
                 qs[0]['NickName'] = username
 
             # if userEmail =='':
             #     qs[0]['userEmail'] = NickName
 
-            if phone =='':
+            if phone == '':
                 qs[0]['phone'] = NickName
 
-
         # if not qs:
         #     uidq = UIDMainUser.objects.filter(UID=UID).values('user_id')
         #     if uidq.exists():
@@ -1051,9 +1057,9 @@ class EquipmentManagerV3(View):
             phone = qs[0]['phone']
             username = qs[0]['username']
             qs = CommonService.qs_to_list(qs)
-            if NickName =='':
+            if NickName == '':
                 qs[0]['NickName'] = username
-            if phone =='':
+            if phone == '':
                 qs[0]['phone'] = NickName
         return response.json(0, qs)
 

+ 25 - 9
Controller/IotCoreController.py

@@ -39,13 +39,13 @@ class IotCoreView(View):
         response = ResponseObject()
         lang = request_dict.get('lang', 'en')
         response.lang = lang
-        if operation == 'createKeysAndCertificate':
+        if operation == 'createKeysAndCertificate':     # 设备注册到IoT core
             return self.create_keys_and_certificate(request_dict, response, request)
         elif operation == 'requestPublishMessage':
             return self.request_publish_message(request_dict, response)
         elif operation == 'getS3PullKey':
             return self.get_s3_pull_key(request_dict, response, request)
-        elif operation == 'thingRegroup':
+        elif operation == 'thingRegroup':   # OTA升级成功重新分组
             return self.thing_regroup(request_dict, response)
         elif operation == 'pcGetIotInfo':
             return self.pcGetIotInfo(request_dict, response)
@@ -167,20 +167,36 @@ class IotCoreView(View):
 
     @staticmethod
     def thing_regroup(request_dict, response):
-        # 物品重新分组
+        """
+        OTA升级成功重新分组
+        @param request_dict: 请求参数
+        @request_dict uid: 设备uid
+        @request_dict region_id: 地区id
+        @request_dict time_stamp: 时间戳
+        @request_dict time_stamp_token: 时间戳token
+        @request_dict device_version: 设备版本
+        @request_dict language: 版本语言
+        @param response: 响应对象
+        @return: response
+        """
         uid = request_dict.get('uid', '')
-        token = request_dict.get('token', None)
-        language = request_dict.get('language', None)
         region_id = request_dict.get('region_id', None)
         time_stamp = request_dict.get('time_stamp', None)
+        time_stamp_token = request_dict.get('time_stamp_token', None)
         device_version = request_dict.get('device_version', None)
+        language = request_dict.get('language', None)
 
-        if not all([token, language, region_id, time_stamp, device_version]):
+        if not all([region_id, time_stamp, time_stamp_token, device_version, language]):
             return response.json(444)
 
         # 时间戳token校验
-        if not CommonService.check_time_stamp_token(token, time_stamp):
-            return response.json(13)
+        no_rtc = request_dict.get('no_rtc', None)
+        if no_rtc:
+            if not CommonService.check_time_stamp_token_without_distance(time_stamp_token, time_stamp):
+                return response.json(13)
+        else:
+            if not CommonService.check_time_stamp_token(time_stamp_token, time_stamp):
+                return response.json(13)
 
         company_mark = '11A'
         thing_name_suffix = uid
@@ -188,7 +204,7 @@ class IotCoreView(View):
             # 使用序列号
             serial_number = request_dict.get('serial_number', None)
             if not serial_number:
-                return response.json(444)
+                return response.json(444, {{'error param': 'uid and serial_number'}})
             company_mark = serial_number[-3:]
             thing_name_suffix = serial_number
             uid = CommonService.query_uid_with_serial(serial_number)

+ 2 - 2
Controller/OrderContrller.py

@@ -128,8 +128,8 @@ class OrderView(View):
                     d['did'] = did['id']
                     d['Type'] = did['Type']
                     # 如果存在序列号返回完整序列号
-                    if did['serial_number'] and did['Type'] == 101:
-                        d['UID'] = CommonService.get_full_serial_number(d['UID'], did['serial_number'], did['Type'])
+                    if did['serial_number']:
+                        d['serial_number'] = CommonService.get_full_serial_number(d['UID'], did['serial_number'], did['Type'])
                     data.append(d)
             d['rank__content'] = d['rank__lang__content']
             del d['rank__lang__content']

+ 26 - 3
Controller/PaymentCycle.py

@@ -19,7 +19,7 @@ from paypalrestsdk.notifications import WebhookEvent
 import logging
 import json
 from paypalrestsdk import BillingPlan
-
+import datetime as date_time
 
 # 周期扣款相关
 class Paypal:
@@ -328,10 +328,9 @@ class PaypalCycleNotify(View):
             billing_agreement_id = paypal_body.get('billing_agreement_id')
             paypal_transaction_id = paypal_body.get('id')
             amount = paypal_body.get('amount')
-
             if event_type != 'PAYMENT.SALE.COMPLETED':
                 logger.info('----钩子异常----')
-
+            self.find_subscription_transactions(billing_agreement_id)
             # self.get_plan_desc('P-4CG284532S612303METMEINY')
             if resource_type == 'sale' and paypal_body.get('state') == 'completed':
                 paypalrestsdk.configure(PAYPAL_CRD)
@@ -530,6 +529,30 @@ class PaypalCycleNotify(View):
             logger.info(repr(e))
             return HttpResponse('fail', status=500)
 
+    @staticmethod
+    def find_subscription_transactions(billing_agreement_id):
+        """
+        列出当前订阅扣款事务
+        @param billing_agreement_id: 协议id
+        @return:
+        """
+        if not billing_agreement_id:
+            return False
+        logger = logging.getLogger('pay')
+        try:
+            paypalrestsdk.configure(PAYPAL_CRD)
+            billing_agreement = paypalrestsdk.BillingAgreement.find(billing_agreement_id)
+            today = date_time.date.today()
+            oneday = date_time.timedelta(days=1)
+            yesterday = today - oneday
+            start_date = yesterday.strftime('%Y-%m-%d')
+            end_date = today.strftime('%Y-%m-%d')
+            transactions = billing_agreement.search_transactions(start_date, end_date)
+            logger.info('--->列出当前扣款事务{}'.format(transactions))
+        except Exception as e:
+            logger.info('出错了~查询订阅的事务异常,errLine:{}, errMsg:{}'.format(e.__traceback__.tb_lineno, repr(e)))
+
+
     def do_subscription_break_notify(self, request_dict, request, response):
         logger = logging.getLogger('pay')
         logger.info('--------进入订阅失败,付款失败,暂停--------')

+ 143 - 6
Controller/SensorGateway/EquipmentFamilyController.py

@@ -19,7 +19,7 @@ from Ansjer.config import OSS_STS_ACCESS_SECRET, OSS_STS_ACCESS_KEY
 from Controller.DeviceConfirmRegion import Device_Region
 from Model.models import Device_Info, UID_Bucket, UID_Preview, UidSetModel, UidChannelSetModel, \
     iotdeviceInfoModel, UIDModel, Device_User, UserFamily, FamilyMember, FamilyMemberPermission, \
-    FamilyRoomDevice, FamilyRoom, FamilyMemberJoin
+    FamilyRoomDevice, FamilyRoom, FamilyMemberJoin, GatewaySubDevice
 from Object.ResponseObject import ResponseObject
 from Object.TokenObject import TokenObject
 from Service.CommonService import CommonService
@@ -90,6 +90,9 @@ class EquipmentFamilyView(View):
             return self.changes_member_permission(user_id, request_dict, response)
         elif operation == 'family/del':
             return self.family_family_del(user_id, request_dict, response)
+        # 首页设备列表
+        elif operation == 'query-device':
+            return self.get_device(user_id, request_dict, response)
         else:
             return response.json(414)
 
@@ -152,7 +155,8 @@ class EquipmentFamilyView(View):
             return response.json(444, {'param': 'nick_name, serial_number, device_type'})
         device_info_qs = Device_Info.objects.filter(serial_number=serial_number, isShare=False)
         if device_info_qs:
-            qs = device_info_qs.values('userID__NickName', 'NickName', 'userID_id')
+            qs = device_info_qs.values('NickName', 'userID_id', 'userID__userEmail', 'userID__phone',
+                                       'userID__username', 'userID__NickName')
             nickname = qs[0]['NickName']
             device_user_id = qs[0]['userID_id']
             if device_user_id == user_id:
@@ -185,7 +189,7 @@ class EquipmentFamilyView(View):
                                            UID=serial_number,
                                            serial_number=serial_number, data_joined=now_time,
                                            update_time=now_time)
-                boole = cls.family_room_device_save(family_id, room_id, device_id)
+                boole = cls.family_room_device_save(family_id, room_id, device_id, device_type)
                 if not boole:
                     return response.json(15)
                 # 判断是否有用户绑定
@@ -727,15 +731,17 @@ class EquipmentFamilyView(View):
             return response.json(444)
 
     @classmethod
-    def family_room_device_save(cls, family_id, room_id, device_id):
+    def family_room_device_save(cls, family_id, room_id, device_id, device_type):
         """
         设备与家庭房间保存
         @param family_id: 家庭id
         @param room_id: 房间id
         @param device_id: 设备id
+        @param device_type: 设备类型
         @return: Boole
         """
         now_time = int(time.time())
+        device_type = int(device_type)
         family_room_device = FamilyRoomDevice.objects.filter(device_id=device_id)
         if family_room_device.exists():
             return False
@@ -745,6 +751,14 @@ class EquipmentFamilyView(View):
             'updated_time': now_time,
             'created_time': now_time
         }
+
+        category = 0 if device_type == 200 else 1
+        data['category'] = category
+        # 查询类别排序
+        family_room_device_qs = FamilyRoomDevice.objects.filter(family_id=int(family_id), category=category).values(
+            'category_sort')
+        if family_room_device_qs.exists():
+            data['category_sort'] = family_room_device_qs[0]['category_sort']
         if room_id:
             room_id = int(room_id)
             if FamilyRoom.objects.filter(id=room_id).exists():
@@ -761,18 +775,23 @@ class EquipmentFamilyView(View):
         @return: True
         """
         device_info_qs = Device_Info.objects.filter(userID=user_id)
-        device_info_qs = device_info_qs.filter(~Q(isExist=0)).values('id')
+        device_info_qs = device_info_qs.filter(~Q(isExist=0)).values('id', 'Type')
         if device_info_qs.exists():
             with transaction.atomic():
                 not_time = time.time()
                 device_list = []
                 for item in device_info_qs:
                     device_id = item['id']
+                    device_type = item['Type']
+                    if device_type == 200:
+                        category = 0
+                    else:
+                        category = 1
                     family_device_qs = FamilyRoomDevice.objects.filter(device_id=device_id)
                     if not family_device_qs.exists():
                         # 设备绑定家庭
                         device_list.append(FamilyRoomDevice(family_id=family_id, device_id=device_id,
-                                                            created_time=not_time,
+                                                            created_time=not_time, category=category,
                                                             updated_time=not_time))
                 if device_list:
                     FamilyRoomDevice.objects.bulk_create(device_list)
@@ -946,3 +965,121 @@ class EquipmentFamilyView(View):
         if user_family_qs.exists():
             return True
         return False
+
+    @classmethod
+    def get_device(cls, user_id, request_dict, response):
+        """
+        首页设备查询
+        @param user_id: 用户id
+        @param request_dict: 请求参数
+        @request_dict page: 页数
+        @request_dict line: 分页大小
+        @request_dict familyId: 家庭id
+        @request_dict roomId: 房间id
+        @param response: 响应对象
+        @return: response
+        """
+        page = request_dict.get('page', None)
+        line = request_dict.get('line', None)
+        family_id = request_dict.get('familyId', None)
+        room_id = request_dict.get('roomId', None)
+
+        if not all([page, line, family_id]):
+            return response.json(444, {'error param': 'page or line or family_id'})
+        page = int(page)
+        line = int(line)
+        device_dict = {
+            'gateways': [],
+            'cameras': [],
+            'sensors': [],
+            'sort': []
+        }
+        permission = cls.get_member_permission_details(user_id, int(family_id))
+        if not permission or permission == '003':
+            return response.json(404)
+        family_room_device_qs = FamilyRoomDevice.objects.filter(Q(family_id=family_id), ~Q(device_id__isExist=2),
+                                                                Q(device__userID=user_id)).values().order_by('sort',
+                                                                                                             '-device__data_joined')
+        if not family_room_device_qs.exists():
+            return response.json(0, device_dict)
+        gateways = []
+        cameras = []
+        sensors = []
+
+        try:
+            category_sort = family_room_device_qs.values('category').annotate(
+                count=Count('category')).values('category', 'category_sort').order_by('category_sort')
+            for item in category_sort:
+                if item['category'] == 0:
+                    item['category_name'] = '网关子设备类'
+                else:
+                    item['category_name'] = '摄像头类'
+            device_dict['sort'] = list(category_sort)
+            if room_id:
+                family_room = FamilyRoom.objects.filter(id=room_id)
+                if not family_room.exists():
+                    return response.json(0, device_dict)
+                family_room_device_qs = family_room_device_qs.filter(room_id=room_id)
+            # 处理网关摄像头
+            gateways_or_cameras_qs = family_room_device_qs.filter(sub_device=0)[(page - 1) * line:page * line]
+            for item in gateways_or_cameras_qs:
+                room_qs = FamilyRoom.objects.filter(id=item['room_id']).values('name')
+                room_name = room_qs[0]['name'] if room_qs.exists() else ''
+                device_qs = Device_Info.objects.filter(id=item['device_id']).values(
+                    'id', 'userID', 'NickName', 'UID', 'View_Account', 'View_Password',
+                    'ChannelIndex',
+                    'Type', 'isShare', 'primaryUserID', 'primaryMaster', 'data_joined',
+                    'vodPrimaryUserID',
+                    'vodPrimaryMaster', 'userID__userEmail', 'version', 'isVod',
+                    'isExist', 'NotificationMode',
+                    'isCameraOpenCloud', 'serial_number'
+                ).first()
+                if device_qs:
+                    device_qs['sensorStatus'] = 0
+                    device_qs['roomName'] = room_name
+                    if device_qs['primaryUserID'] and device_qs['id'] == device_qs['primaryUserID']:
+                        device_qs['isPrimaryUser'] = 1
+                    else:
+                        device_qs['isPrimaryUser'] = 0
+                    if 'data_joined' in device_qs:
+                        if device_qs['data_joined']:
+                            device_qs['data_joined'] = device_qs['data_joined'].strftime("%Y-%m-%d %H:%M:%S")
+                        else:
+                            device_qs['data_joined'] = ''
+                    if device_qs['Type'] == 200:
+                        gateways.append(device_qs)
+                    else:
+                        cameras.append(device_qs)
+            # 处理传感器
+            sensors_qs = family_room_device_qs.filter(~Q(sub_device=0))
+            for item in sensors_qs:  # 查询传感器
+                sub_device_qs = GatewaySubDevice.objects.filter(id=item['sub_device']).values()
+                if sub_device_qs.exists():
+                    sub_device_dict = {
+                        "id": sub_device_qs[0]['id'],
+                        "NickName": sub_device_qs[0]['nickname'],
+                        "Type": sub_device_qs[0]['device_type'],
+                        'sensorStatus': sub_device_qs[0]['status'],
+                    }
+                    sensors.append(sub_device_dict)
+            device_dict['sensors'] = sensors
+
+            device_list = [gateways, cameras]
+            for index, item in enumerate(device_list):
+                uid_list = []
+                for dvl in item:
+                    uid_list.append(dvl['UID'])
+                # 设备关联套餐,设备预览图
+                uid_bucket_qs, uid_preview_qs = cls.get_bucket_and_preview_by_uid(uid_list)
+                # 设备配置信息
+                uid_set_dict = cls.get_uid_set_dict(uid_list)
+                # 设备详情信息
+                result = cls.get_device_details(item, uid_bucket_qs, uid_preview_qs, uid_set_dict)
+                if index == 0:
+                    device_dict['gateways'] = result
+                else:
+                    device_dict['cameras'] = result
+
+            return response.json(0, device_dict)
+        except Exception as e:
+            return response.json(500, repr(e))

+ 87 - 3
Controller/SensorGateway/GatewayDeviceController.py

@@ -6,18 +6,21 @@
 @Email   : zhangdongming@asj6.wecom.work
 @Software: PyCharm
 """
+import time
+
 from django.db import transaction
 from django.db.models import Q
 from django.views.generic.base import View
 
+from Ansjer.Config.gatewaySensorConfig import SMART_SCENE_TOPIC
 from Controller.SensorGateway.EquipmentFamilyController import EquipmentFamilyView
 from Model.models import FamilyRoomDevice, FamilyRoom, GatewaySubDevice, Device_Info, UserFamily, FamilyMember, \
-    UidSetModel, iotdeviceInfoModel
+    UidSetModel, iotdeviceInfoModel, SmartScene, SceneLog
 from Object.ResponseObject import ResponseObject
 from Object.TokenObject import TokenObject
+from Service.CommonService import CommonService
 
 
-# 网关主页
 class GatewayDeviceView(View):
 
     def get(self, request, *args, **kwargs):
@@ -108,6 +111,9 @@ class GatewayDeviceView(View):
         device_info_qs = Device_Info.objects.filter(userID_id=user_id, id=device_id)
         if device_info_qs.exists():
             device_info_qs.update(NickName=device_name)
+            uid_set_qs = UidSetModel.objects.filter(uid=device_info_qs[0].UID)
+            if uid_set_qs.exists():
+                uid_set_qs.update(nickname=device_name)
         return response.json(0)
 
     @classmethod
@@ -160,6 +166,26 @@ class GatewayDeviceView(View):
                         uid_set_qs = UidSetModel.objects.filter(uid=device_qs.first().UID)
                         if uid_set_qs.exists():
                             uid_set_qs.delete()
+                        smart_scene_qs = SmartScene.objects.filter(device_id=device_id)
+                        if smart_scene_qs.exists():
+                            # 通知设备删除场景id
+                            serial_number = device_qs.first().serial_number
+                            topic_name = SMART_SCENE_TOPIC.format(serial_number)
+                            smart_scene_info = smart_scene_qs.values('id')
+                            for smart_scene in smart_scene_info:
+                                msg = {
+                                    'smart_scene_delete': int(smart_scene['id'])
+                                }
+                                success = CommonService.req_publish_mqtt_msg(serial_number, topic_name, msg, 0)
+                                try:
+                                    assert success
+                                except AssertionError:
+                                    return response.json(10044)
+                                time.sleep(0.3)
+                            smart_scene_qs.delete()
+                        scene_log_qs = SceneLog.objects.filter(device_id=device_id)
+                        if scene_log_qs.exists():
+                            scene_log_qs.delete()
                         device_qs.delete()
                 elif sub_ids:
                     sub_ids = sub_ids.split(',')
@@ -167,12 +193,45 @@ class GatewayDeviceView(View):
                     for item in sub_ids:
                         sub_id = int(item)
                         ids.append(sub_id)
+                        sub_device_qs = GatewaySubDevice.objects.filter(id=sub_id).values('device_type', 'src_addr',
+                                                                                          'device__serial_number')
+                        serial_number = sub_device_qs[0]['device__serial_number']
+                        topic_name = SMART_SCENE_TOPIC.format(serial_number)
+                        device_type = sub_device_qs[0]['device_type']
+                        if device_type == 216:  # 删除智能按钮通知设备
+                            msg = {
+                                'sos_delete': int(sub_device_qs[0]['src_addr'], 16)
+                            }
+                            success = CommonService.req_publish_mqtt_msg(serial_number, topic_name, msg, 0)
+                            try:
+                                assert success
+                            except AssertionError:
+                                return response.json(10044)
+                            time.sleep(0.3)
                     family_device_qs = FamilyRoomDevice.objects.filter(sub_device__in=ids)
                     if family_device_qs.exists():
                         family_device_qs.delete()
                     gateway_sub_qs = GatewaySubDevice.objects.filter(id__in=ids)
                     if gateway_sub_qs.exists():
                         gateway_sub_qs.delete()
+                    smart_scene_qs = SmartScene.objects.filter(sub_device_id__in=ids)
+                    if smart_scene_qs.exists():
+                        smart_scene_info = smart_scene_qs.values('id')
+                        for smart_scene in smart_scene_info:
+                            # 通知设备删除场景id
+                            msg = {
+                                'smart_scene_delete': int(smart_scene['id'])
+                            }
+                            success = CommonService.req_publish_mqtt_msg(serial_number, topic_name, msg, 0)
+                            try:
+                                assert success
+                            except AssertionError:
+                                return response.json(10044)
+                            time.sleep(0.3)
+                        smart_scene_qs.delete()
+                    scene_log_qs = SceneLog.objects.filter(sub_device_id__in=ids)
+                    if scene_log_qs.exists():
+                        scene_log_qs.delete()
                 return response.json(0)
         except Exception as e:
             print(e)
@@ -228,10 +287,12 @@ class GatewayDeviceView(View):
             family_device_qs = family_device_qs.filter(~Q(sub_device=0)).order_by('-created_time')
 
             sub_device = []
+            sub_id_list = []
             if family_device_qs.exists():
                 family_device_qs = family_device_qs.values()
                 for item in family_device_qs:
                     sub_id = item['sub_device']
+                    sub_id_list.append(sub_id)
                     gateway_sub_qs = GatewaySubDevice.objects.filter(device_id=device_id, id=sub_id).values(
                         'id', 'device_type',
                         'nickname',
@@ -255,9 +316,32 @@ class GatewayDeviceView(View):
                         'ieeeAddr': gateway_sub_qs['ieee_addr'],
                         'familyId': family_id,
                     })
-            res = {'gateway': gateway, 'sub_device': sub_device, 'sub_device_count': len(sub_device), 'scene_count': 0}
+            scene_count = SmartScene.objects.filter(Q(device_id=device_id) | Q(sub_device_id__in=sub_id_list)).count()
+            res = {'gateway': gateway, 'sub_device': sub_device, 'sub_device_count': len(sub_device),
+                   'scene_count': scene_count}
             return response.json(0, res)
 
         except Exception as e:
             print(e.args)
             return response.json(500)
+
+#
+#                   ___====-_  _-====___
+#             _--^^^#####//      \\#####^^^--_
+#          _-^##########// (    ) \\##########^-_
+#         -############//  |\^^/|  \\############-
+#       _/############//   (@::@)   \\############\_
+#      /#############((     \\//     ))#############\
+#     -###############\\    (oo)    //###############-
+#    -#################\\  / VV \  //#################-
+#   -###################\\/      \//###################-
+#  _#/|##########/\######(   /\   )######/\##########|\#_
+#  |/ |#/\#/\#/\/  \#/\##\  |  |  /##/\#/  \/\#/\#/\#| \|
+#  `  |/  V  V  `   V  \#\| |  | |/#/  V   '  V  V  \|  '
+#     `   `  `      `   / | |  | | \   '      '  '   '
+#                      (  | |  | |  )
+#                     __\ | |  | | /__
+#                    (vvv(VVV)(VVV)vvv)
+#                         神兽保佑
+#                        代码无BUG!
+#

+ 11 - 2
Controller/SensorGateway/GatewayFamilyMemberController.py

@@ -13,6 +13,7 @@ import time
 from django.db import transaction
 from django.views.generic.base import View
 
+from Ansjer.config import SERVER_DOMAIN
 from Controller.SensorGateway.EquipmentFamilyController import EquipmentFamilyView
 from Model.models import UserFamily, FamilyMemberJoin, FamilyMember, SysMsgModel, FamilyMemberPermission, \
     Device_User, FamilyRoomDevice, FamilyRoom
@@ -111,6 +112,9 @@ class GatewayFamilyMemberView(View):
         family_id = int(family_id)
         try:
             with transaction.atomic():
+                family_count = UserFamily.objects.filter(user_id=app_user_id).count()
+                if family_count <= 1:
+                    return response.json(10058)
                 family_member_qs = FamilyMember.objects.filter(family_id=family_id, identity=0)
                 if family_member_qs.exists():
                     return response.json(10057)
@@ -537,14 +541,19 @@ class GatewayFamilyMemberView(View):
         if not user_family_qs.exists():
             return response.json(173)
         user_family_qs = user_family_qs.values('id', 'name', 'user__userEmail',
-                                               'user__userIconUrl',
+                                               'user__userIconPath',
                                                'user__phone', 'user__NickName',
                                                'user__username')
+        user_icon_url = ''
+        userIconPath = str(user_family_qs[0]['user__userIconPath'])
+        if userIconPath and userIconPath.find('static/') != -1:
+            userIconPath = userIconPath.replace('static/', '').replace('\\', '/')
+            user_icon_url = SERVER_DOMAIN + 'account/getAvatar/' + userIconPath
         return response.json(0, {
             'familyId': user_family_qs[0]['id'],
             'userPhone': user_family_qs[0]['user__phone'],
             'nickName': user_family_qs[0]['user__NickName'],
-            'userIconUrl': user_family_qs[0]['user__userIconUrl'],
+            'userIconUrl': user_icon_url,
             'userName': user_family_qs[0]['user__username'],
             'familyName': user_family_qs[0]['name'],
             'userEmail': user_family_qs[0]['user__userEmail'],

+ 180 - 40
Controller/SensorGateway/GatewayFamilyRoomController.py

@@ -12,7 +12,7 @@ from django.db.models import Q, Count, F
 from django.views.generic.base import View
 
 from Controller.SensorGateway.EquipmentFamilyController import EquipmentFamilyView
-from Model.models import FamilyRoomDevice, FamilyRoom
+from Model.models import FamilyRoomDevice, FamilyRoom, GatewaySubDevice, Device_Info
 from Object.ResponseObject import ResponseObject
 from Object.TokenObject import TokenObject
 
@@ -50,10 +50,14 @@ class GatewayFamilyRoomView(View):
         # 房间详情
         elif operation == 'details':
             return self.get_room_details(app_user_id, request_dict, response)
-        elif operation == 'all-devices':    # 家庭所有设备
+        elif operation == 'all-devices':  # 家庭所有设备
             return self.all_devices(request_dict, response)
-        elif operation == 'devices-sort':    # 家庭设备排序
+        elif operation == 'devices-sort':  # 家庭设备排序
             return self.devices_sort(request_dict, response)
+        elif operation == 'device-category':  # 获取设备类别
+            return self.device_category(request_dict, response)
+        elif operation == 'category-sort':  # 设备类别排序
+            return self.category_sort(request_dict, response)
         else:
             return response.json(414)
 
@@ -85,12 +89,17 @@ class GatewayFamilyRoomView(View):
                 if qs.exists():
                     qs.update(room_id=0, sort=0)
                 if device_ids:
-                    device_ids = device_ids.split(',')
+                    device_ids = eval(device_ids)
                     for i, item in enumerate(device_ids):
-                        device_id = int(item)
-                        device_qs = FamilyRoomDevice.objects.filter(device_id=device_id)
+                        device_id = item['id']
+                        device_type = item['type']
+                        device_qs = Device_Info.objects.filter(id=device_id, Type=device_type)
                         if device_qs.exists():
-                            device_qs.update(room_id=room_id, sort=i)
+                            room_device_qs = FamilyRoomDevice.objects.filter(device_id=device_id)
+                        else:
+                            room_device_qs = FamilyRoomDevice.objects.filter(sub_device=device_id)
+                        if room_device_qs.exists():
+                            room_device_qs.update(room_id=room_id, sort=i)
                 return response.json(0)
         except Exception as e:
             print(e)
@@ -167,36 +176,65 @@ class GatewayFamilyRoomView(View):
             return response.json(404)
         family_id = int(family_id)
         room_id = int(room_id)
-        room_device_qs = FamilyRoomDevice.objects.filter(family_id=family_id, room_id=room_id).order_by('sort').values(
-            'device_id').annotate(count=Count('device_id')).values('device_id', 'device__Type', 'device__NickName')
+        room_device_qs = FamilyRoomDevice.objects.filter(family_id=family_id, room_id=room_id).values(
+            'device_id', 'device__Type', 'device__NickName', 'sub_device').order_by('sort', '-device__data_joined')
         device_room = []
         if room_device_qs.exists():
             room_name = FamilyRoom.objects.filter(id=room_id)
             for item in room_device_qs:
-                device_room.append({
-                    'deviceId': item['device_id'],
-                    'deviceType': item['device__Type'],
-                    'nickName': item['device__NickName'],
-                    'roomName': room_name.first().name if room_name.exists() else '',
-                })
+                if not item['sub_device']:
+                    device_dict = {
+                        'deviceId': item['device_id'],
+                        'deviceType': item['device__Type'],
+                        'nickName': item['device__NickName'],
+                        'roomName': room_name.first().name if room_name.exists() else '',
+                    }
+                else:
+                    sub_device_qs = GatewaySubDevice.objects.filter(id=item['sub_device']).values('id',
+                                                                                                  'device_type',
+                                                                                                  'nickname')
+                    if not sub_device_qs.exists():
+                        continue
+                    device_dict = {
+                        'deviceId': sub_device_qs[0]['id'],
+                        'deviceType': sub_device_qs[0]['device_type'],
+                        'nickName': sub_device_qs[0]['nickname'],
+                        'roomName': room_name.first().name if room_name.exists() else '',
+                    }
+
+                device_room.append(device_dict)
 
         device_not_room = []
         device_not_room_qs = FamilyRoomDevice.objects.filter(family_id=family_id)
-        device_not_room_qs = device_not_room_qs.filter(~Q(room_id=room_id)).values('device_id').annotate(
-            count=Count('device_id')).values('room_id', 'device_id', 'device__Type', 'device__NickName')
+        device_not_room_qs = device_not_room_qs.filter(~Q(room_id=room_id)).values('room_id', 'device_id',
+                                                                                   'device__Type', 'device__NickName',
+                                                                                   'sub_device').order_by('sort',
+                                                                                                          '-device__data_joined')
         if device_not_room_qs.exists():
             for item in device_not_room_qs:
                 name = ''
-                if room_device_qs.exists():
-                    family_room_qs = FamilyRoom.objects.filter(id=item['room_id'])
-                    if family_room_qs.exists():
-                        name = family_room_qs.first().name
-                device_not_room.append({
-                    'deviceId': item['device_id'],
-                    'deviceType': item['device__Type'],
-                    'nickName': item['device__NickName'],
-                    'roomName': name
-                })
+                family_room_qs = FamilyRoom.objects.filter(id=item['room_id'])
+                if family_room_qs.exists():
+                    name = family_room_qs.first().name
+                if not item['sub_device']:
+                    device_not_room.append({
+                        'deviceId': item['device_id'],
+                        'deviceType': item['device__Type'],
+                        'nickName': item['device__NickName'],
+                        'roomName': name
+                    })
+                else:
+                    sub_device_qs = GatewaySubDevice.objects.filter(id=item['sub_device']).values('id',
+                                                                                                  'device_type',
+                                                                                                  'nickname')
+                    if not sub_device_qs.exists():
+                        continue
+                    device_not_room.append({
+                        'deviceId': sub_device_qs[0]['id'],
+                        'deviceType': sub_device_qs[0]['device_type'],
+                        'nickName': sub_device_qs[0]['nickname'],
+                        'roomName': name
+                    })
         return response.json(0, {'deviceRooms': device_room, 'deviceNotRooms': device_not_room})
 
     @staticmethod
@@ -212,21 +250,67 @@ class GatewayFamilyRoomView(View):
         if not family_id:
             return response.json(444)
         try:
-            family_room_device_qs = FamilyRoomDevice.objects.filter(family_id=family_id, sub_device=0).\
-                annotate(type=F('device__Type'), nickname=F('device__NickName')).\
-                values('device_id', 'type', 'nickname', 'room_id').order_by('sort')
+            family_room_device_qs = FamilyRoomDevice.objects.filter(family_id=family_id).values('device_id',
+                                                                                                'device__Type',
+                                                                                                'device__NickName',
+                                                                                                'room_id',
+                                                                                                'sub_device',
+                                                                                                'category',
+                                                                                                ).order_by(
+                'sort', '-device__data_joined')
+
             if not family_room_device_qs.exists():
                 return response.json(0, [])
+            sort = FamilyRoomDevice.objects.filter(family_id=family_id).values('category').annotate(
+                count=Count('category')).values('category', 'category_sort').order_by('category_sort')
+            for item in sort:
+                if item['category'] == 0:
+                    item['category_name'] = '网关子设备类'
+                else:
+                    item['category_name'] = '摄像头类'
+            gateways = []
+            cameras = []
             # 查询房间名称
             for device in family_room_device_qs:
                 room_id = device['room_id']
-                if room_id == 0:
-                    device['room'] = ''
-                else:
-                    family_room_qs = FamilyRoom.objects.filter(id=room_id).values('name')
-                    device['room'] = family_room_qs[0]['name'] if family_room_qs.exists() else ''
-                device.pop('room_id')
-            return response.json(0, list(family_room_device_qs))
+                device_type = device['device__Type']
+                category = device['category']
+                room_name = FamilyRoom.objects.filter(id=room_id)
+                if category == 0:  # 网关子设备
+                    if not device['sub_device']:
+                        device_dict = {
+                            'deviceId': device['device_id'],
+                            'deviceType': device_type,
+                            'nickName': device['device__NickName'],
+                            'roomName': room_name.first().name if room_name.exists() else '',
+                        }
+                    else:
+                        sub_device_qs = GatewaySubDevice.objects.filter(id=device['sub_device']).values('device_type',
+                                                                                                        'nickname')
+                        if not sub_device_qs.exists():
+                            continue
+                        device_dict = {
+                            'deviceId': device['sub_device'],
+                            'deviceType': sub_device_qs[0]['device_type'],
+                            'nickName': sub_device_qs[0]['nickname'],
+                            'roomName': room_name.first().name if room_name.exists() else '',
+                        }
+
+                    gateways.append(device_dict)
+
+                else:  # 摄像头设备
+                    cameras.append({
+                        'deviceId': device['device_id'],
+                        'deviceType': device_type,
+                        'nickName': device['device__NickName'],
+                        'roomName': room_name.first().name if room_name.exists() else '',
+                    })
+            device_room = {
+                'gateways': gateways,
+                'cameras': cameras,
+                'sort': list(sort)
+            }
+            return response.json(0, device_room)
         except Exception as e:
             return response.json(500, repr(e))
 
@@ -243,11 +327,67 @@ class GatewayFamilyRoomView(View):
         if not device_ids:
             return response.json(444)
         try:
-            device_ids = device_ids.split(',')
+            device_ids = eval(device_ids)
             with transaction.atomic():
                 for i, item in enumerate(device_ids):
-                    device_id = int(item)
-                    FamilyRoomDevice.objects.filter(device_id=device_id).update(sort=i)
+                    device_id = item['id']
+                    device_type = item['type']
+                    device_qs = Device_Info.objects.filter(id=device_id, Type=device_type)
+                    if device_qs.exists():  # 更新主设备排序
+                        FamilyRoomDevice.objects.filter(device_id=device_id).update(sort=i)
+                    else:  # 更新子设备排序
+                        FamilyRoomDevice.objects.filter(sub_device=device_id).update(sort=i)
+            return response.json(0)
+        except Exception as e:
+            return response.json(500, repr(e))
+
+    @staticmethod
+    def device_category(request_dict, response):
+        """
+        获取设备类别排序
+        @param request_dict: 请求参数
+        @request_dict 家庭id: family_id
+        @param response: 响应参数
+        @return:
+        """
+        family_id = request_dict.get('familyId', None)
+        if not family_id:
+            return response.json(444)
+        try:
+            family_room_device_qs = FamilyRoomDevice.objects.filter(family_id=family_id).values('category').annotate(
+                count=Count('category')).values('category', 'category_sort').order_by('category_sort')
+            for item in family_room_device_qs:
+                if item['category'] == 0:
+                    item['category_name'] = '网关子设备类'
+                else:
+                    item['category_name'] = '摄像头类'
+            return response.json(0, list(family_room_device_qs))
+        except Exception as e:
+            return response.json(500, repr(e))
+
+    @staticmethod
+    def category_sort(request_dict, response):
+        """
+        家庭设备排序
+        @param request_dict: 请求参数
+        @request_dict 家庭id: family_id
+        @request_dict 排序列表: category_sort
+        @param response: 响应参数
+        @return:
+        """
+        family_id = request_dict.get('familyId', None)
+        category_sort = request_dict.get('categorySort', None)
+        if not all([family_id, category_sort]):
+            return response.json(444)
+        try:
+            category_sort_list = eval(category_sort)
+            family_room_device_qs = FamilyRoomDevice.objects.filter(family_id=family_id)
+            if family_room_device_qs.exists():
+                with transaction.atomic():
+                    for item in category_sort_list:
+                        category = item['category']
+                        category_sort = item['category_sort']
+                        family_room_device_qs.filter(category=category).update(category_sort=category_sort)
             return response.json(0)
         except Exception as e:
             return response.json(500, repr(e))

+ 915 - 0
Controller/SensorGateway/SmartSceneController.py

@@ -0,0 +1,915 @@
+# -*- coding: utf-8 -*-
+"""
+@Author : Rocky
+@Time : 2022/6/29 9:31
+@File :SmartSceneController.py
+"""
+import json
+import time
+
+from django.core.exceptions import ObjectDoesNotExist
+from django.db import transaction
+from django.db.models import F, Q, Count
+from django.views import View
+
+from Ansjer.Config.gatewaySensorConfig import SMART_SCENE_TOPIC, SENSOR_TYPE, EVENT_TYPE
+from Model.models import FamilyRoomDevice, GatewaySubDevice, FamilyRoom, SmartScene, EffectiveTime, Device_Info, \
+    SceneLog
+from Object.ResponseObject import ResponseObject
+from Service.CommonService import CommonService
+
+
+class SmartSceneView(View):
+    def get(self, request, *args, **kwargs):
+        request.encoding = 'utf-8'
+        operation = kwargs.get('operation')
+        return self.validation(request.GET, request, operation)
+
+    def post(self, request, *args, **kwargs):
+        request.encoding = 'utf-8'
+        operation = kwargs.get('operation')
+        return self.validation(request.POST, request, operation)
+
+    def validation(self, request_dict, request, operation):
+        if operation == 'get-scene':  # 设备获取智能场景数据
+            return self.get_scene_data(request_dict, ResponseObject('cn'))
+        token_code, user_id, response = CommonService.verify_token_get_user_id(request_dict, request)
+        if token_code != 0:
+            return response.json(token_code)
+        if operation == 'condition-devices':  # 添加条件-查询设备
+            return self.condition_devices(request_dict, response)
+        elif operation == 'task-devices':  # 添加任务-查询设备
+            return self.task_devices(request_dict, response)
+        elif operation == 'create':  # 创建智能场景
+            return self.create_smart_scene(request_dict, user_id, response)
+        elif operation == 'scene-list':  # 查询智能场景列表
+            return self.scene_list(request_dict, user_id, response)
+        elif operation == 'smart-button-scene-list':  # 查询智能按钮场景列表
+            return self.smart_button_scene_list(request_dict, user_id, response)
+        elif operation == 'update-status':  # 更新智能场景状态
+            return self.update_status(request_dict, response)
+        elif operation == 'detail':  # 查询智能场景详情
+            return self.scene_detail(request_dict, response)
+        elif operation == 'edit':  # 编辑智能场景
+            return self.edit_smart_scene(request_dict, user_id, response)
+        elif operation == 'delete':  # 删除智能场景
+            return self.delete_smart_scene(request_dict, response)
+        elif operation == 'log':  # 查询智能场景日志
+            return self.scene_log(request_dict, response)
+        elif operation == 'log-date':  # 查询智能场景日志日期
+            return self.scene_log_date(request_dict, response)
+        else:
+            return response.json(414)
+
+    @classmethod
+    def condition_devices(cls, request_dict, response):
+        """
+        添加条件-查询设备
+        @param request_dict: 请求参数
+        @request_dict deviceId: 网关设备id
+        @request_dict subDeviceId: 子设备id
+        @param response: 响应对象
+        @return: response
+        """
+        device_id = request_dict.get('deviceId', None)
+        sub_device_id = request_dict.get('subDeviceId', None)
+        if not any([device_id, sub_device_id]):
+            return response.json(444, {'error param': 'deviceId or subDeviceId'})
+        try:
+            if sub_device_id:
+                device_id = GatewaySubDevice.objects.get(id=sub_device_id).device_id
+            gateway_sub_device_qs = GatewaySubDevice.objects.filter(device_id=device_id)
+            if not gateway_sub_device_qs.exists():
+                return response.json(173)
+            res = cls.get_sub_device_room_name(gateway_sub_device_qs)
+            return response.json(0, res)
+        except Exception as e:
+            return response.json(500, repr(e))
+
+    @classmethod
+    def task_devices(cls, request_dict, response):
+        """
+        添加任务-查询设备
+        @param request_dict: 请求参数
+        @request_dict deviceId: 网关设备id
+        @param response: 响应对象
+        @return: response
+        """
+        sub_device_id = request_dict.get('subDeviceId', None)
+        device_id = request_dict.get('deviceId', None)
+
+        if not any([device_id, sub_device_id]):
+            return response.json(444, {'error param': 'deviceId or subDeviceId'})
+        try:
+
+            if device_id:
+                res = [cls.get_gateway_data(device_id)]
+            else:
+                sub_device_qs = GatewaySubDevice.objects.filter(id=sub_device_id).values('device_id', 'device_type')
+                device_id = sub_device_qs[0]['device_id']
+                device_type = sub_device_qs[0]['device_type']
+
+                if device_type != SENSOR_TYPE['smart_button']:  # 非智能按钮只返回网关
+                    res = [cls.get_gateway_data(device_id)]
+                else:
+                    gateway_data = cls.get_gateway_data(device_id)
+                    sub_device_qs = GatewaySubDevice.objects.filter(
+                        Q(device_id=device_id) & Q(device_type=SENSOR_TYPE['door_magnet']) | Q(
+                            device_type=SENSOR_TYPE['body_sensor'])).values('id', 'nickname', 'status', 'device_type')
+                    if not sub_device_qs.exists():
+                        return response.json(173)
+                    res = cls.get_sub_device_room_name(sub_device_qs, gateway_data)
+
+            return response.json(0, res)
+        except Exception as e:
+            return response.json(500, repr(e))
+
+    @staticmethod
+    def get_sub_device_room_name(sub_device_qs, gateway_data=None):
+        """
+        获取房间名称
+        @param sub_device_qs: 子设备信息
+        @param gateway_data: 网关参数
+        @return: sub_device_list
+        """
+        sub_device_list = []
+        if gateway_data:
+            sub_device_list.append(gateway_data)
+        sub_device_qs = sub_device_qs.annotate(gatewaySubId=F('id'),
+                                               deviceType=F('device_type'),
+                                               deviceNickName=F('nickname')). \
+            values('gatewaySubId', 'deviceType', 'deviceNickName', 'status')
+        for sub_device in sub_device_qs:
+            family_room_device_qs = FamilyRoomDevice.objects.filter(sub_device=sub_device['gatewaySubId']). \
+                values('room_id')
+            if not family_room_device_qs.exists():
+                sub_device['roomName'] = ''
+            else:
+                room_id = family_room_device_qs[0]['room_id']
+                try:
+                    sub_device['roomName'] = FamilyRoom.objects.get(id=room_id).name
+                except ObjectDoesNotExist:
+                    sub_device['roomName'] = ''
+            sub_device_list.append(sub_device)
+        return sub_device_list
+
+    @staticmethod
+    def get_gateway_data(device_id):
+        """
+        获取网关数据
+        @param device_id: 网关设备id
+        @return: res
+        """
+        device_info_qs = Device_Info.objects.filter(id=device_id).values('NickName', 'Type')
+        nickname = device_info_qs[0]['NickName']
+        device_type = device_info_qs[0]['Type']
+        room_id = FamilyRoomDevice.objects.filter(device_id=device_id).values('room_id')[0]['room_id']
+        room_id_qs = FamilyRoom.objects.filter(id=room_id).values('name')
+        room_name = room_id_qs.first()['name'] if room_id_qs.exists() else ''
+        res = {
+            'deviceNickName': nickname,
+            'deviceType': device_type,
+            'roomName': room_name,
+            'status': 1,
+        }
+        return res
+
+    @staticmethod
+    def create_smart_scene(request_dict, user_id, response):
+        """
+        创建智能场景
+        @param request_dict: 请求参数
+        @param user_id: 用户id
+        @request_dict deviceId: 网关设备id
+        @request_dict subDeviceId: 子设备id
+        @request_dict sceneName: 场景名称
+        @request_dict conditions: 条件
+        @request_dict tasks: 任务
+        @request_dict isAllDay: 是否全天执行
+        @request_dict startTime: 开始时间
+        @request_dict endTime: 结束时间
+        @request_dict repeat: 重复周期
+        @param response: 响应对象
+        @return: response
+        """
+        device_id = request_dict.get('deviceId', None)
+        sub_device_id = request_dict.get('subDeviceId', None)
+        scene_name = request_dict.get('sceneName', None)
+        conditions = request_dict.get('conditions', None)
+        tasks = request_dict.get('tasks', None)
+        is_all_day = request_dict.get('isAllDay', None)
+
+        if not all([scene_name, conditions, tasks]):
+            return response.json(444, {'error param': 'scene_name and conditions and tasks'})
+
+        now_time = int(time.time())
+        conditions_dict = eval(conditions)
+        tasks_list = eval(tasks)
+
+        try:
+            # 判断是否已存在该场景名
+            smart_scene_qs = SmartScene.objects.filter(user_id=user_id, scene_name=scene_name)
+            if smart_scene_qs.exists():
+                return response.json(179)
+
+            smart_scene_dict = {
+                'user_id': user_id,
+                'scene_name': scene_name,
+                'conditions': conditions,
+                'tasks': tasks,
+                'created_time': now_time,
+                'updated_time': now_time,
+            }
+            msg = {
+                'scene_status': 1
+            }
+            # 处理设置时间
+            if is_all_day is not None:
+                is_all_day = int(is_all_day)
+                smart_scene_dict['is_all_day'] = is_all_day
+
+            # 处理传网关设备id和子设备id的情况
+            if conditions_dict['type'] == 1:  # 网关设置时间
+                if not device_id:
+                    return response.json(444, {'error param': 'deviceId'})
+                smart_scene_dict['device_id'] = device_id
+                device_info_qs = Device_Info.objects.filter(id=device_id).values('serial_number')
+                if not device_info_qs.exists():
+                    return response.json(173)
+                serial_number = device_info_qs[0]['serial_number']
+                msg['sensor_delay'] = tasks_list[0]['delay_time']
+            else:  # 子设备设置场景
+                if not sub_device_id:
+                    return response.json(444, {'error param': 'subDeviceId'})
+
+                device_type = int(conditions_dict['sensor']['device_type'])
+                # 智能按钮不能创建触发条件相同的场景
+                if device_type == SENSOR_TYPE['smart_button']:
+                    event_type = conditions_dict['sensor']['eventValues'][0]['event_type']
+                    smart_scene_qs = SmartScene.objects.filter(sub_device_id=sub_device_id,
+                                                               conditions__contains=event_type)
+                    if smart_scene_qs.exists():
+                        return response.json(180)
+
+                # 温湿度传感器返回温湿度
+                elif device_type == SENSOR_TYPE['tem_hum_sensor']:
+                    event_values = conditions_dict['sensor']['eventValues'][0]
+                    if '≥' in event_values['value']:
+                        replace_str = '≥ '
+                        msg['sensor_symbol'] = 2
+                    else:
+                        replace_str = '≤ '
+                        msg['sensor_symbol'] = 1
+                    value = event_values['value'].replace(replace_str, '')
+                    msg['sensor_data'] = float(value)
+
+                smart_scene_dict['sub_device_id'] = sub_device_id
+                sub_device_qs = GatewaySubDevice.objects.filter(id=sub_device_id).values('device__serial_number',
+                                                                                         'src_addr')
+                if not sub_device_qs.exists():
+                    return response.json(173)
+                serial_number = sub_device_qs[0]['device__serial_number']
+
+                msg['sensor_type'] = int(conditions_dict['sensor']['device_type'])
+                msg['sensor_src'] = int(sub_device_qs[0]['src_addr'], 16)
+                msg['sensor_status'] = int(conditions_dict['sensor']['eventValues'][0]['event_type'])
+
+            with transaction.atomic():
+                if is_all_day is None:  # 不设置时间
+                    smart_scene_qs = SmartScene.objects.create(**smart_scene_dict)
+                    # 设备的time数据,分钟转为秒
+                    time_dict = {
+                        'start_time': conditions_dict['time']['minutes'] * 60,
+                        'repeat': conditions_dict['time']['repeat']
+                    }
+                elif is_all_day == 1:  # 全天
+                    smart_scene_qs = SmartScene.objects.create(**smart_scene_dict)
+                    # 设备的time数据
+                    time_dict = {
+                        'is_all_day': is_all_day
+                    }
+                elif is_all_day == 2:  # 非全天
+                    start_time = int(request_dict.get('startTime', None))
+                    end_time = int(request_dict.get('endTime', None))
+                    repeat = int(request_dict.get('repeat', None))
+                    effective_time_qs = EffectiveTime.objects.filter(start_time=start_time, end_time=end_time,
+                                                                     repeat=repeat).values('id')
+                    if effective_time_qs.exists():
+                        effective_time_id = effective_time_qs[0]['id']
+                    else:
+                        effective_time_id = EffectiveTime.objects.create(start_time=start_time, end_time=end_time,
+                                                                         repeat=repeat).id
+                    smart_scene_dict['effective_time_id'] = effective_time_id
+                    smart_scene_qs = SmartScene.objects.create(**smart_scene_dict)
+
+                    # 设备的time数据,分钟转为秒
+                    time_dict = {
+                        'is_all_day': is_all_day,
+                        'start_time': start_time * 60,
+                        'end_time': end_time * 60,
+                        'repeat': repeat
+                    }
+                else:
+                    return response.json(444, {'error param': 'invalid isAllDay'})
+
+                msg['time'] = time_dict
+                msg['smart_scene_id'] = smart_scene_qs.id
+                task_list = []
+                for task in tasks_list:
+                    task_temp = {
+                        'sensor_type': int(task['device_type']),
+                        'sensor_action': int(task['event_type'])
+                    }
+                    sub_device_id = task.get('subDeviceId', None)
+                    if sub_device_id:
+                        sub_device_qs = GatewaySubDevice.objects.filter(id=sub_device_id).values('src_addr').first()
+                        task_temp['sensor_src'] = int(sub_device_qs['src_addr'], 16)
+                    task_list.append(task_temp)
+                msg['task'] = task_list
+
+                smart_scene_qs.device_data = json.dumps(msg)
+                smart_scene_qs.save()
+                # 发布MQTT消息通知网关设备
+                thing_name = serial_number
+                topic_name = SMART_SCENE_TOPIC.format(serial_number)
+
+                success = CommonService.req_publish_mqtt_msg(thing_name, topic_name, msg, 0)
+                try:
+                    assert success
+                except AssertionError:
+                    return response.json(10044)
+
+            return response.json(0)
+        except Exception as e:
+            return response.json(500, repr(e))
+
+    @staticmethod
+    def scene_list(request_dict, user_id, response):
+        """
+        查询智能场景列表
+        @param request_dict: 请求参数
+        @param user_id: 用户id
+        @request_dict deviceId: 网关设备id
+        @request_dict subDeviceId: 子设备id
+        @param response: 响应对象
+        @return: response
+        """
+        device_id = request_dict.get('deviceId', None)
+        sub_device_id = request_dict.get('subDeviceId', None)
+
+        if not any([device_id, sub_device_id]):
+            return response.json(444, {'error param': 'deviceId or subDeviceId'})
+        try:
+            if device_id:
+                sub_device_id = GatewaySubDevice.objects.filter(device_id=device_id).values('id')
+                smart_scene_qs = SmartScene.objects.filter(
+                    Q(user_id=user_id) & Q(device_id=device_id) | Q(sub_device_id__in=sub_device_id))
+            else:
+                smart_scene_qs = SmartScene.objects.filter(user_id=user_id, sub_device_id=sub_device_id)
+            if not smart_scene_qs.exists():
+                return response.json(173)
+            smart_scene_qs = smart_scene_qs.values('id', 'scene_name', 'is_enable')
+            return response.json(0, list(smart_scene_qs))
+        except Exception as e:
+            return response.json(500, repr(e))
+
+    @staticmethod
+    def smart_button_scene_list(request_dict, user_id, response):
+        """
+        查询智能按钮场景列表
+        @param request_dict: 请求参数
+        @param user_id: 用户id
+        @request_dict subDeviceId: 子设备id
+        @param response: 响应对象
+        @return: response
+        """
+        sub_device_id = request_dict.get('subDeviceId', None)
+
+        if not sub_device_id:
+            return response.json(444, {'error param': 'subDeviceId'})
+        try:
+            click_scene_qs = SmartScene.objects.filter(user_id=user_id, sub_device_id=sub_device_id,
+                                                       conditions__contains=str(
+                                                           EVENT_TYPE['smart_button_click'])).values('id', 'scene_name',
+                                                                                                     'is_enable')
+            double_click_scene_qs = SmartScene.objects.filter(user_id=user_id, sub_device_id=sub_device_id,
+                                                              conditions__contains=str(
+                                                                  EVENT_TYPE['smart_button_double_click'])). \
+                values('id', 'scene_name', 'is_enable')
+            three_click_scene_qs = SmartScene.objects.filter(user_id=user_id, sub_device_id=sub_device_id,
+                                                             conditions__contains=str(
+                                                                 EVENT_TYPE['smart_button_three_click'])). \
+                values('id', 'scene_name', 'is_enable')
+            scene_list = []
+            if click_scene_qs.exists():
+                scene_list.append({
+                    'trigger_type': 1,
+                    'id': click_scene_qs[0]['id'],
+                    'scene_name': click_scene_qs[0]['scene_name'],
+                    'is_enable': click_scene_qs[0]['is_enable']
+                })
+            if double_click_scene_qs.exists():
+                scene_list.append({
+                    'trigger_type': 2,
+                    'id': double_click_scene_qs[0]['id'],
+                    'scene_name': double_click_scene_qs[0]['scene_name'],
+                    'is_enable': double_click_scene_qs[0]['is_enable']
+                })
+            if three_click_scene_qs.exists():
+                scene_list.append({
+                    'trigger_type': 3,
+                    'id': three_click_scene_qs[0]['id'],
+                    'scene_name': three_click_scene_qs[0]['scene_name'],
+                    'is_enable': three_click_scene_qs[0]['is_enable']
+                })
+            return response.json(0, scene_list)
+        except Exception as e:
+            return response.json(500, repr(e))
+
+    @staticmethod
+    def update_status(request_dict, response):
+        """
+        更新智能场景状态
+        @param request_dict: 请求参数
+        @request_dict smartSceneId: 智能场景id
+        @request_dict isEnable: 状态,True or False
+        @param response: 响应对象
+        @return: response
+        """
+        smart_scene_id = request_dict.get('smartSceneId', None)
+        is_enable = request_dict.get('isEnable', None)
+
+        if not all([smart_scene_id, is_enable]):
+            return response.json(444, {'error param': 'smartSceneId and status'})
+        try:
+            smart_scene_id = int(smart_scene_id)
+            scene_status = 1 if is_enable == 'True' else 0
+            msg = {
+                'scene_id': smart_scene_id,
+                'scene_status': scene_status
+            }
+            # 查询序列号
+            smart_scene_qs = SmartScene.objects.filter(id=smart_scene_id).values('device_id', 'sub_device_id')
+            device_id = smart_scene_qs[0]['device_id']
+            if device_id:
+                serial_number = Device_Info.objects.filter(id=device_id).values('serial_number')[0]['serial_number']
+            else:
+                sub_device_id = smart_scene_qs[0]['sub_device_id']
+                serial_number = GatewaySubDevice.objects.filter(id=sub_device_id).values('device__serial_number')[0][
+                    'device__serial_number']
+
+            topic_name = SMART_SCENE_TOPIC.format(serial_number)
+
+            with transaction.atomic():
+                SmartScene.objects.filter(id=smart_scene_id).update(is_enable=is_enable)
+                # 通过mqtt发送设备数据
+                success = CommonService.req_publish_mqtt_msg(serial_number, topic_name, msg, 0)
+                try:
+                    assert success
+                except AssertionError:
+                    return response.json(10044)
+            return response.json(0)
+        except Exception as e:
+            return response.json(500, repr(e))
+
+    @staticmethod
+    def scene_detail(request_dict, response):
+        """
+        查询智能场景详情
+        @param request_dict: 请求参数
+        @request_dict smartSceneId: 智能场景id
+        @param response: 响应对象
+        @return: response
+        """
+        smart_scene_id = request_dict.get('smartSceneId', None)
+
+        if not smart_scene_id:
+            return response.json(444, {'error param': 'smartSceneId'})
+        try:
+            smart_scene_qs = SmartScene.objects.filter(id=smart_scene_id).values('id', 'scene_name', 'conditions',
+                                                                                 'tasks', 'effective_time_id',
+                                                                                 'is_all_day')
+            if not smart_scene_qs.exists():
+                return response.json(173)
+            res = {
+                'scene_name': smart_scene_qs[0]['scene_name'],
+                'condition': eval(smart_scene_qs[0]['conditions']),
+                'task': eval(smart_scene_qs[0]['tasks']),
+            }
+
+            # 如果存在关联的时间数据,组织时间数据
+            is_all_day = smart_scene_qs[0]['is_all_day']
+            effectiveTime = {}
+            if is_all_day != 0:
+                effectiveTime['isAllDay'] = is_all_day
+            if is_all_day == 2:
+                try:
+                    effective_time_qs = EffectiveTime.objects.get(id=smart_scene_qs[0]['effective_time_id'])
+                    effectiveTime['startTime'] = effective_time_qs.start_time
+                    effectiveTime['endTime'] = effective_time_qs.end_time
+                    effectiveTime['repeat'] = effective_time_qs.repeat
+                except ObjectDoesNotExist:
+                    return response.json(0, res)
+            res['effectiveTime'] = effectiveTime
+            return response.json(0, res)
+
+        except Exception as e:
+            return response.json(500, repr(e))
+
+    @staticmethod
+    def edit_smart_scene(request_dict, user_id, response):
+        """
+        编辑智能场景
+        @param request_dict: 请求参数
+        @param user_id: 用户id
+        @request_dict smartSceneId: 智能场景id
+        @param response: 响应对象
+        @return: response
+        """
+        smart_scene_id = int(request_dict.get('smartSceneId', None))
+        device_id = request_dict.get('deviceId', None)
+        sub_device_id = request_dict.get('subDeviceId', None)
+        scene_name = request_dict.get('sceneName', None)
+        conditions = request_dict.get('conditions', None)
+        tasks = request_dict.get('tasks', None)
+        is_all_day = request_dict.get('isAllDay', None)
+
+        conditions_dict = eval(conditions)
+        tasks_list = eval(tasks)
+        now_time = int(time.time())
+
+        smart_scene_qs = SmartScene.objects.filter(user_id=user_id, scene_name=scene_name).filter(~Q(id=smart_scene_id))
+        if smart_scene_qs.exists():
+            return response.json(179)
+
+        res = {
+            'scene_name': scene_name,
+            'conditions': conditions_dict,
+            'tasks': tasks_list
+        }
+        effective_time = {}
+
+        if is_all_day:
+            is_all_day = int(is_all_day)
+            effective_time['is_all_day'] = is_all_day
+
+        if not all([smart_scene_id, scene_name, conditions, tasks]):
+            return response.json(444, {'error param': 'smartSceneId,sceneName,conditions or tasks'})
+        try:
+            smart_scene_qs = SmartScene.objects.filter(id=smart_scene_id)
+            if not smart_scene_qs.exists():
+                return response.json(173)
+
+            scene_status = 1 if smart_scene_qs[0].is_enable else 0
+            msg = {
+                'smart_scene_id': smart_scene_id,
+                'scene_status': scene_status
+            }
+            if conditions_dict['type'] == 2:  # 条件为选择子设备
+                if not sub_device_id:
+                    return response.json(444, {'error param': 'subDeviceId'})
+
+                device_type = int(conditions_dict['sensor']['device_type'])
+                # 智能按钮不能创建触发条件相同的场景
+                if device_type == SENSOR_TYPE['smart_button']:
+                    event_type = conditions_dict['sensor']['eventValues'][0]['event_type']
+                    smart_scene_temp_qs = SmartScene.objects.filter(Q(sub_device_id=sub_device_id),
+                                                                    ~Q(id=smart_scene_id),
+                                                                    conditions__contains=event_type)
+                    if smart_scene_temp_qs.exists():
+                        return response.json(180)
+
+                # 温湿度传感器返回温湿度
+                elif device_type == SENSOR_TYPE['tem_hum_sensor']:
+                    event_values = conditions_dict['sensor']['eventValues'][0]
+                    if '≥' in event_values['value']:
+                        replace_str = '≥ '
+                        msg['sensor_symbol'] = 2
+                    else:
+                        replace_str = '≤ '
+                        msg['sensor_symbol'] = 1
+                    value = event_values['value'].replace(replace_str, '')
+                    msg['sensor_data'] = float(value)
+
+                device_id = ''
+                sub_device_qs = GatewaySubDevice.objects.filter(id=sub_device_id).values('src_addr',
+                                                                                         'device__serial_number')
+                if not sub_device_qs.exists():
+                    return response.json(173)
+                serial_number = sub_device_qs[0]['device__serial_number']
+                msg['sensor_type'] = int(conditions_dict['sensor']['device_type'])
+                msg['sensor_src'] = int(sub_device_qs[0]['src_addr'], 16)
+                msg['sensor_status'] = int(conditions_dict['sensor']['eventValues'][0]['event_type'])
+            else:
+                if not device_id:
+                    return response.json(444, {'error param': 'deviceId'})
+                sub_device_id = 0
+                device_qs = Device_Info.objects.filter(id=device_id).values('serial_number')
+                if not device_qs.exists():
+                    return response.json(173)
+                serial_number = device_qs[0]['serial_number']
+                msg['sensor_delay'] = tasks_list[0]['delay_time']
+
+            task_list = []
+            for task in tasks_list:
+                task_temp = {
+                    'sensor_type': int(task['device_type']),
+                    'sensor_action': int(task['event_type'])
+                }
+                task_sub_device_id = task.get('subDeviceId', None)
+                if task_sub_device_id:
+                    sub_device_qs = GatewaySubDevice.objects.filter(id=task_sub_device_id).values('src_addr').first()
+                    task_temp['sensor_src'] = int(sub_device_qs['src_addr'], 16)
+                task_list.append(task_temp)
+            msg['task'] = task_list
+
+            with transaction.atomic():
+                smart_scene_qs.update(scene_name=scene_name, conditions=conditions, tasks=tasks,
+                                      device_data=json.dumps(msg), updated_time=now_time, device_id=device_id,
+                                      sub_device_id=sub_device_id)
+
+                if is_all_day is None:  # 不设置时间或全天
+                    smart_scene_qs.update(effective_time_id=0, is_all_day=0)
+                    time_dict = {
+                        'start_time': conditions_dict['time']['minutes'] * 60,
+                        'repeat': conditions_dict['time']['repeat']
+                    }
+                elif is_all_day == 1:
+                    smart_scene_qs.update(effective_time_id=0, is_all_day=is_all_day)
+                    time_dict = {
+                        'is_all_day': is_all_day
+                    }
+                else:
+                    start_time = int(request_dict.get('startTime', None))
+                    end_time = int(request_dict.get('endTime', None))
+                    repeat = int(request_dict.get('repeat', None))
+                    effective_time_qs = EffectiveTime.objects.filter(start_time=start_time, end_time=end_time,
+                                                                     repeat=repeat).values('id')
+                    if effective_time_qs.exists():
+                        effective_time_id = effective_time_qs[0]['id']
+                    else:
+                        effective_time_id = EffectiveTime.objects.create(start_time=start_time, end_time=end_time,
+                                                                         repeat=repeat).id
+                    smart_scene_qs.update(effective_time_id=effective_time_id, is_all_day=is_all_day)
+                    time_dict = {
+                        'is_all_day': is_all_day,
+                        'start_time': start_time * 60,
+                        'end_time': end_time * 60,
+                        'repeat': repeat
+                    }
+                    effective_time = {
+                        'isAllDay': is_all_day,
+                        'startTime': start_time,
+                        'endTime': end_time,
+                        'repeat': repeat
+                    }
+                msg['time'] = time_dict
+
+            # 通过mqtt发送设备数据
+            thing_name = serial_number
+            topic_name = SMART_SCENE_TOPIC.format(serial_number)
+            success = CommonService.req_publish_mqtt_msg(thing_name, topic_name, msg, 0)
+            try:
+                assert success
+            except AssertionError:
+                return response.json(10044)
+
+            res['effectiveTime'] = effective_time
+            return response.json(0, res)
+
+        except Exception as e:
+            return response.json(500, repr(e))
+
+    @staticmethod
+    def delete_smart_scene(request_dict, response):
+        """
+        删除智能场景
+        @param request_dict: 请求参数
+        @request_dict smartSceneIds: 智能场景id
+        @param response: 响应对象
+        @return: response
+        """
+        smart_scene_ids = request_dict.get('smartSceneIds', None)
+
+        if not smart_scene_ids:
+            return response.json(444, {'error param': 'smartSceneIds'})
+        try:
+            smart_scene_id_list = smart_scene_ids.split(',')
+            # 获取序列号
+            smart_scene_id = smart_scene_id_list[0]
+            smart_scene_qs = SmartScene.objects.filter(id=smart_scene_id).values('device_id', 'sub_device_id')
+            device_id = smart_scene_qs[0]['device_id']
+            if device_id:
+                serial_number = Device_Info.objects.filter(id=device_id).values('serial_number')[0]['serial_number']
+            else:
+                serial_number = GatewaySubDevice.objects.filter(id=smart_scene_qs[0]['sub_device_id']). \
+                    values('device__serial_number')[0]['device__serial_number']
+            topic_name = SMART_SCENE_TOPIC.format(serial_number)
+            with transaction.atomic():
+                SmartScene.objects.filter(id__in=smart_scene_id_list).delete()
+                for smart_scene_id in smart_scene_id_list:
+                    # 通知设备删除场景id
+                    msg = {
+                        'smart_scene_delete': int(smart_scene_id)
+                    }
+                    success = CommonService.req_publish_mqtt_msg(serial_number, topic_name, msg, 0)
+                    try:
+                        assert success
+                    except AssertionError:
+                        return response.json(10044)
+                    time.sleep(0.3)
+            return response.json(0)
+        except Exception as e:
+            return response.json(500, repr(e))
+
+    @staticmethod
+    def scene_log(request_dict, response):
+        """
+        查询场景日志
+        @param request_dict: 请求参数
+        @request_dict deviceId: 网关id
+        @request_dict subDeviceId: 子设备id
+        @request_dict page: 页数
+        @request_dict size: 条数
+        @request_dict startTime: 开始时间
+        @request_dict endTime: 结束时间
+        @param response: 响应对象
+        @return: response
+        """
+        family_id = request_dict.get('familyId', None)
+        page = request_dict.get('page', None)
+        size = request_dict.get('size', None)
+        start_time = request_dict.get('startTime', None)
+        end_time = request_dict.get('endTime', None)
+
+        if not all([family_id, page, size]):
+            return response.json(444, {'error param': 'page or size'})
+
+        device_list = []
+        sub_device_list = []
+        family_room_device_qs = FamilyRoomDevice.objects.filter(family_id=family_id).values('device_id', 'sub_device')
+        for item in family_room_device_qs:
+            if item['sub_device'] and item['sub_device'] not in sub_device_list:
+                sub_device_list.append(item['sub_device'])
+            if item['device_id'] not in device_list:
+                device_list.append(item['device_id'])
+
+        try:
+            page, size = int(page), int(size)
+            scene_log_qs = SceneLog.objects.filter(
+                Q(device_id__in=device_list) | Q(sub_device_id__in=sub_device_list))
+            if start_time and end_time:
+                scene_log_qs = scene_log_qs.filter(created_time__range=(start_time, end_time)).values(
+                    'status',
+                    'created_time',
+                    'device_id',
+                    'sub_device_id',
+                    'scene_name',
+                    'tasks').order_by(
+                    '-created_time')[(page - 1) * size:page * size]
+            else:
+                scene_log_qs = scene_log_qs.values('status',
+                                                   'created_time', 'device_id', 'sub_device_id', 'scene_name',
+                                                   'tasks').order_by(
+                    '-created_time')[(page - 1) * size:page * size]
+            if not scene_log_qs.exists():
+                return response.json(0, [])
+            for item in scene_log_qs:
+                device_id = item['device_id']
+                sub_device_id = item['sub_device_id']
+                if device_id:
+                    qs = Device_Info.objects.filter(id=device_id).values('Type')
+                    item['device_type'] = qs[0]['Type']
+                else:
+                    qs = GatewaySubDevice.objects.filter(id=sub_device_id).values('device_type')
+                    item['device_type'] = qs[0]['device_type']
+                item['tasks'] = eval(item['tasks'])
+            return response.json(0, list(scene_log_qs))
+        except Exception as e:
+            print(repr(e))
+            return response.json(500, repr(e))
+
+    @staticmethod
+    def scene_log_date(request_dict, response):
+        """
+        查询场景日志日期
+        @param request_dict: 请求参数
+        @request_dict deviceId: 网关id
+        @request_dict subDeviceId: 子设备id
+        @param response: 响应对象
+        @return: response
+        """
+        family_id = request_dict.get('familyId', None)
+
+        if not family_id:
+            return response.json(444, {'error param': 'device_id and gatewaySubId'})
+        device_list = []
+        sub_device_list = []
+        family_room_device_qs = FamilyRoomDevice.objects.filter(family_id=family_id).values('device_id', 'sub_device')
+        for item in family_room_device_qs:
+            if item['sub_device'] and item['sub_device'] not in sub_device_list:
+                sub_device_list.append(item['sub_device'])
+            if item['device_id'] not in device_list:
+                device_list.append(item['device_id'])
+
+        try:
+            scene_log_qs = SceneLog.objects.extra(
+                select={'date': "FROM_UNIXTIME(created_time,'%%Y-%%m-%%d')"}).values('date'). \
+                               filter(Q(device_id__in=device_list) | Q(sub_device_id__in=sub_device_list)). \
+                               annotate(count=Count('created_time')). \
+                               order_by('-date')[:31]
+            log_date_list = []
+            for scene_log in scene_log_qs:
+                log_date_list.append({
+                    'timestamp': CommonService.str_to_timestamp(scene_log['date'], '%Y-%m-%d'),
+                    'count': scene_log['count'],
+                    'format': scene_log['date'],
+                })
+            return response.json(0, log_date_list)
+        except Exception as e:
+            return response.json(500, repr(e))
+
+    @staticmethod
+    def get_scene_data(request_dict, response):
+        """
+        设备获取智能场景数据
+        @param request_dict: 请求参数
+        @request_dict serial_number: 序列号
+        @param response: 响应对象
+        @return: response
+        """
+        serial_number = request_dict.get('serial_number', None)
+
+        if not serial_number:
+            return response.json(444, {'error param': 'serial_number'})
+
+        try:
+            device_info_qs = Device_Info.objects.filter(serial_number=serial_number).values('id')
+            if not device_info_qs.exists():
+                return response.json(173)
+            device_id = device_info_qs[0]['id']
+            sub_device_id_list = GatewaySubDevice.objects.filter(device_id=device_id).values_list('id', flat=True)
+            if sub_device_id_list:
+                smart_scene_qs = SmartScene.objects.filter(
+                    Q(device_id=device_id) | Q(sub_device_id__in=sub_device_id_list))
+            else:
+                smart_scene_qs = SmartScene.objects.filter(device_id=device_id)
+            if not smart_scene_qs.exists():
+                return response.json(173)
+
+            # 下发智能场景数据
+            smart_scene_qs = smart_scene_qs.values('device_data')
+            topic_name = SMART_SCENE_TOPIC.format(serial_number)
+            for smart_scene in smart_scene_qs:
+                msg = eval(smart_scene['device_data'])
+                success = CommonService.req_publish_mqtt_msg(serial_number, topic_name, msg, 0)
+                try:
+                    assert success
+                except AssertionError:
+                    return response.json(10044)
+                time.sleep(2)
+
+            # 下发智能按钮数据
+            smart_button_qs = GatewaySubDevice.objects.filter(device_id=device_id,
+                                                              device_type=SENSOR_TYPE['smart_button']).values(
+                'src_addr', 'is_tampered')
+            if smart_button_qs.exists():
+                sos_count = smart_button_qs.count()
+                for index, smart_button in enumerate(smart_button_qs):
+                    msg = {
+                        'sos_count': sos_count,  # 该网关下的智能按钮数量
+                        'sos_num': index + 1,  # 第几个按钮
+                        'sensor_src': int(smart_button['src_addr'], 16),
+                        'sos_select': smart_button['is_tampered']
+                    }
+                    success = CommonService.req_publish_mqtt_msg(serial_number, topic_name, msg, 0)
+                    try:
+                        assert success
+                    except AssertionError:
+                        return response.json(10044)
+                    time.sleep(2)
+
+            return response.json(0)
+        except Exception as e:
+            return response.json(500, repr(e))
+
+#
+#                   ___====-_  _-====___
+#             _--^^^#####//      \\#####^^^--_
+#          _-^##########// (    ) \\##########^-_
+#         -############//  |\^^/|  \\############-
+#       _/############//   (@::@)   \\############\_
+#      /#############((     \\//     ))#############\
+#     -###############\\    (oo)    //###############-
+#    -#################\\  / VV \  //#################-
+#   -###################\\/      \//###################-
+#  _#/|##########/\######(   /\   )######/\##########|\#_
+#  |/ |#/\#/\#/\/  \#/\##\  |  |  /##/\#/  \/\#/\#/\#| \|
+#  `  |/  V  V  `   V  \#\| |  | |/#/  V   '  V  V  \|  '
+#     `   `  `      `   / | |  | | \   '      '  '   '
+#                      (  | |  | |  )
+#                     __\ | |  | | /__
+#                    (vvv(VVV)(VVV)vvv)
+#                         神兽保佑
+#                        代码无BUG!
+#

+ 315 - 90
Controller/SensorGateway/SubDeviceController.py

@@ -8,12 +8,11 @@ import time
 from collections import OrderedDict
 
 from django.db import transaction
-from django.db.models import Count
+from django.db.models import Count, Q
 from django.views import View
 
-from Model.models import Device_Info, GatewaySubDevice, FamilyRoomDevice, SensorRecord
-from Object.ResponseObject import ResponseObject
-from Object.TokenObject import TokenObject
+from Ansjer.Config.gatewaySensorConfig import SMART_SCENE_TOPIC, SENSOR_TYPE, EVENT_TYPE
+from Model.models import Device_Info, GatewaySubDevice, FamilyRoomDevice, SensorRecord, SmartScene, SceneLog, FamilyRoom
 from Service.CommonService import CommonService
 
 
@@ -29,13 +28,9 @@ class GatewaySubDeviceView(View):
         return self.validation(request.POST, request, operation)
 
     def validation(self, request_dict, request, operation):
-        token_obj = TokenObject(request.META.get('HTTP_AUTHORIZATION'))
-        lang = request_dict.get('lang', None)
-        response = ResponseObject(lang if lang else token_obj.lang)
-
-        if token_obj.code != 0:
-            return response.json(token_obj.code)
-        user_id = token_obj.userID
+        token_code, user_id, response = CommonService.verify_token_get_user_id(request_dict, request)
+        if token_code != 0:
+            return response.json(token_code)
         if operation == 'add':  # 添加子设备
             return self.add_sub_device(request_dict, user_id, response)
         elif operation == 'detail':  # 查询子设备信息
@@ -43,13 +38,19 @@ class GatewaySubDeviceView(View):
         elif operation == 'update':  # 更新子设备信息
             return self.sensor_update(request_dict, response)
         elif operation == 'delete':  # 删除子设备
-            return self.delete(request_dict, user_id, response)
+            return self.delete_sub_device(request_dict, response)
         elif operation == 'records/tem-hum':  # 查询温湿度传感器记录
             return self.records_tem_hum(request_dict, response)
         elif operation == 'records':  # 查询其他传感器记录
             return self.records(request_dict, response)
         elif operation == 'records-date':  # 查询传感器记录日期
             return self.records_date(request_dict, response)
+        elif operation == 'home':  # 查询传感器主页信息
+            return self.sensor_home_info(request_dict, response)
+        elif operation == 'update-emergency-status':  # 更新智能按钮紧急开关状态
+            return self.update_emergency_status(request_dict, response)
+        elif operation == 'list':  # 获取子设备信息
+            return self.get_sensor_list(request_dict, response)
         else:
             return response.json(414)
 
@@ -93,6 +94,7 @@ class GatewaySubDeviceView(View):
         if not all([serial_number, device_type, nickname, src_addr, family_id]):
             return response.json(444)
         now_time = int(time.time())
+        is_tampered = 1 if device_type == SENSOR_TYPE['smart_button'] else 0  # 智能按钮默认开启紧急开关
         try:
             # 查询网关设备数据
             device_info_qs = Device_Info.objects.filter(userID_id=user_id, serial_number=serial_number).values('id')
@@ -102,6 +104,7 @@ class GatewaySubDeviceView(View):
             # 查询是否已添加过该子设备
             sub_device_qs = GatewaySubDevice.objects.filter(device_id=device_id, ieee_addr=ieee_addr)
             if sub_device_qs.exists():
+                sub_device_qs.update(src_addr=src_addr)  # 更新短地址
                 return response.json(174)
 
             with transaction.atomic():
@@ -109,11 +112,24 @@ class GatewaySubDeviceView(View):
                                                              nickname=nickname, ieee_addr=ieee_addr, src_addr=src_addr,
                                                              status=1, mac=mac, device_model=device_model,
                                                              manufacturer=manufacturer, sensor_serial=sensor_serial,
-                                                             firmware_version=firmware_version,
+                                                             firmware_version=firmware_version, is_tampered=is_tampered,
                                                              hardware_version=hardware_version,
                                                              created_time=now_time, updated_time=now_time)
-                FamilyRoomDevice.objects.create(family_id=family_id, room_id=room_id, device_id=device_id,
-                                                sub_device=sub_device.id, created_time=now_time, updated_time=now_time)
+                if device_type == 216:
+                    sub_device.is_tampered = 1
+                    sub_device.save()
+                family_room_device_qs = FamilyRoomDevice.objects.filter(family_id=family_id, category=0).values(
+                    'category_sort')
+                if family_room_device_qs.exists():
+                    FamilyRoomDevice.objects.create(family_id=family_id, room_id=room_id, device_id=device_id,
+                                                    sub_device=sub_device.id, created_time=now_time,
+                                                    updated_time=now_time,
+                                                    category_sort=family_room_device_qs[0]['category_sort'])
+                else:
+                    FamilyRoomDevice.objects.create(family_id=family_id, room_id=room_id, device_id=device_id,
+                                                    sub_device=sub_device.id, created_time=now_time,
+                                                    updated_time=now_time)
+
             return response.json(0)
         except Exception as e:
             return response.json(500, repr(e))
@@ -134,7 +150,9 @@ class GatewaySubDeviceView(View):
         try:
             gateway_sub_device_qs = GatewaySubDevice.objects.filter(id=sub_device_id).values('manufacturer',
                                                                                              'device_model',
-                                                                                             'mac', 'sensor_serial')
+                                                                                             'mac', 'sensor_serial',
+                                                                                             'device_type',
+                                                                                             'is_tampered')
             if not gateway_sub_device_qs.exists():
                 return response.json(173)
             res = {
@@ -143,6 +161,8 @@ class GatewaySubDeviceView(View):
                 'mac': gateway_sub_device_qs[0]['mac'],
                 'sensor_serial': gateway_sub_device_qs[0]['sensor_serial'],
             }
+            if gateway_sub_device_qs[0]['device_type'] == SENSOR_TYPE['smart_button']:  # 智能按钮返回紧急开关状态
+                res['emergency_status'] = gateway_sub_device_qs[0]['is_tampered']
             return response.json(0, res)
         except Exception as e:
             return response.json(500, repr(e))
@@ -177,12 +197,11 @@ class GatewaySubDeviceView(View):
             return response.json(500, repr(e))
 
     @staticmethod
-    def delete(request_dict, user_id, response):
+    def delete_sub_device(request_dict, response):
         """
         更新子设备信息
         @param request_dict: 请求参数
         @request_dict sub_device_id: 子设备id
-        @param user_id: 用户id
         @param response: 响应对象
         @return: response
         """
@@ -191,19 +210,26 @@ class GatewaySubDeviceView(View):
         if not all([sub_device_id]):
             return response.json(444)
         try:
-            GatewaySubDevice.objects.filter(id=sub_device_id).delete()
+            with transaction.atomic():
+                GatewaySubDevice.objects.filter(id=sub_device_id).delete()
+                smart_scene_qs = SmartScene.objects.filter(sub_device_id=sub_device_id)
+                if smart_scene_qs.exists():
+                    smart_scene_qs.delete()
+                scene_log_qs = SceneLog.objects.filter(sub_device_id=sub_device_id)
+                if scene_log_qs.exists():
+                    scene_log_qs.delete()
             return response.json(0)
         except Exception as e:
             return response.json(500, repr(e))
 
-    @staticmethod
-    def records_tem_hum(request_dict, response):
+    @classmethod
+    def records_tem_hum(cls, request_dict, response):
         """
         查询温湿度传感器记录
         @param request_dict: 请求参数
         @request_dict gatewaySubId: 子设备id
         @request_dict cycle: 时间周期
-        @request_dict eventType: 事件类型, 18:温度,19:湿度
+        @request_dict eventType: 事件类型, 2200:温度,2201:湿度
         @param response: 响应对象
         @return: response
         """
@@ -212,75 +238,20 @@ class GatewaySubDeviceView(View):
         event_type = request_dict.get('eventType', None)
         if not all([sub_device_id, cycle, event_type]):
             return response.json(444, {'error param': 'gatewaySubId or cycle or eventType'})
+
         now_time = int(time.time())
+        # 判断event_type
+        event_type = int(event_type)
+        if event_type != EVENT_TYPE['temperature'] and event_type != EVENT_TYPE['humidity']:
+            return response.json(444, {'invalid eventType': event_type})
+
         try:
-            record_dict = OrderedDict()
+            record_dict = cls.get_record_dict(cycle, now_time, sub_device_id, event_type)
             record_list = []
-            if cycle == 'Hours':
-                start_time = now_time - 24 * 60 * 60
-                sensor_record_qs = SensorRecord.objects.filter(gateway_sub_device_id=sub_device_id,
-                                                               event_type=event_type,
-                                                               created_time__range=(start_time, now_time)). \
-                    values('alarm', 'created_time').order_by('created_time')
-                if not sensor_record_qs.exists():
-                    return response.json(0, {'records': [], 'time': now_time})
-
-                for sensor_record in sensor_record_qs:
-                    created_time = time.strftime('%m/%d %H:%M %w', time.localtime(sensor_record['created_time']))
-                    hour = int(created_time[-7:-5])
-                    minute = int(created_time[-4:-2])
-                    if hour != 23 and minute > 30:  # 不为23时且分钟大于30,hour+1
-                        hour += 1
-                    alarm = float(sensor_record['alarm'])
-                    # 组织数据,record_dict:{"0": [1.0, 2.0, 3.0], "1": [1.0, 2.0, 3.0]...}
-                    if str(hour) in record_dict:
-                        record_dict[str(hour)].append(alarm)
-                    else:
-                        record_dict[str(hour)] = [alarm]
-
-            elif cycle == 'Week':
-                start_time = now_time - 24 * 60 * 60 * 7
-                sensor_record_qs = SensorRecord.objects.filter(gateway_sub_device_id=sub_device_id,
-                                                               event_type=event_type,
-                                                               created_time__range=(start_time, now_time)). \
-                    values('alarm', 'created_time').order_by('created_time')
-                if not sensor_record_qs.exists():
-                    return response.json(0, {'records': [], 'time': now_time})
-
-                for sensor_record in sensor_record_qs:
-                    created_time = time.strftime('%m/%d %H:%M %w', time.localtime(sensor_record['created_time']))
-                    week = int(created_time[-1:])
-                    alarm = float(sensor_record['alarm'])
-                    # 组织数据,record_dict:{"0": [1.0, 2.0, 3.0], "1": [1.0, 2.0, 3.0]...}
-                    if str(week) in record_dict:
-                        record_dict[str(week)].append(alarm)
-                    else:
-                        record_dict[str(week)] = [alarm]
-
-            elif cycle == 'Month':
-                start_time = now_time - 24 * 60 * 60 * 30
-                sensor_record_qs = SensorRecord.objects.filter(gateway_sub_device_id=sub_device_id,
-                                                               event_type=event_type,
-                                                               created_time__range=(start_time, now_time)). \
-                    values('alarm', 'created_time').order_by('created_time')
-                if not sensor_record_qs.exists():
-                    return response.json(0, {'records': [], 'time': now_time})
-
-                for sensor_record in sensor_record_qs:
-                    created_time = time.strftime('%m/%d %H:%M %w', time.localtime(sensor_record['created_time']))
-                    month = int(created_time[:2])
-                    day = int(created_time[3:5])
-                    date = str(month) + '/' + str(day)
-                    alarm = float(sensor_record['alarm'])
-                    # 组织数据,record_dict:{"0": [1.0, 2.0, 3.0], "1": [1.0, 2.0, 3.0]...}
-                    if date in record_dict:
-                        record_dict[date].append(alarm)
-                    else:
-                        record_dict[date] = [alarm]
-
-            # 组织响应数据列表,value为每 小时/天 的平均值
-            for k, v in record_dict.items():
-                record_list.append({'key': k, 'value': round(sum(v) / len(v), 1)})
+            if record_dict:
+                # 组织响应数据列表,value为每 小时/天 的平均值
+                for k, v in record_dict.items():
+                    record_list.append({'key': k, 'value': round(sum(v) / len(v), 1)})
 
             res = {
                 'records': record_list,
@@ -290,6 +261,81 @@ class GatewaySubDeviceView(View):
         except Exception as e:
             return response.json(500, repr(e))
 
+    @staticmethod
+    def get_record_dict(cycle, now_time, sub_device_id, event_type):
+        """
+        获取记录数据
+        @param cycle: 时间周期
+        @param now_time: 当前时间
+        @param sub_device_id: 子设备id
+        @param event_type: 事件类型, 2200:温度,2201:湿度
+        @return: record_dict: 记录数据
+        """
+        record_dict = OrderedDict()
+        if cycle == 'Hours':
+            start_time = now_time - 24 * 60 * 60
+            sensor_record_qs = SensorRecord.objects.filter(gateway_sub_device_id=sub_device_id,
+                                                           event_type=event_type,
+                                                           created_time__range=(start_time, now_time)). \
+                values('alarm', 'created_time').order_by('created_time')
+            if not sensor_record_qs.exists():
+                return record_dict
+
+            for sensor_record in sensor_record_qs:
+                created_time = time.strftime('%m/%d %H:%M %w', time.localtime(sensor_record['created_time']))
+                hour = int(created_time[-7:-5])
+                minute = int(created_time[-4:-2])
+                if hour != 23 and minute > 30:  # 不为23时且分钟大于30,hour+1
+                    hour += 1
+                alarm = float(sensor_record['alarm'])
+                # 组织数据,record_dict:{"0": [1.0, 2.0, 3.0], "1": [1.0, 2.0, 3.0]...}
+                if str(hour) in record_dict:
+                    record_dict[str(hour)].append(alarm)
+                else:
+                    record_dict[str(hour)] = [alarm]
+
+        elif cycle == 'Week':
+            start_time = now_time - 24 * 60 * 60 * 7
+            sensor_record_qs = SensorRecord.objects.filter(gateway_sub_device_id=sub_device_id,
+                                                           event_type=event_type,
+                                                           created_time__range=(start_time, now_time)). \
+                values('alarm', 'created_time').order_by('created_time')
+            if not sensor_record_qs.exists():
+                return record_dict
+
+            for sensor_record in sensor_record_qs:
+                created_time = time.strftime('%m/%d %H:%M %w', time.localtime(sensor_record['created_time']))
+                week = int(created_time[-1:])
+                alarm = float(sensor_record['alarm'])
+                # 组织数据,record_dict:{"0": [1.0, 2.0, 3.0], "1": [1.0, 2.0, 3.0]...}
+                if str(week) in record_dict:
+                    record_dict[str(week)].append(alarm)
+                else:
+                    record_dict[str(week)] = [alarm]
+
+        elif cycle == 'Month':
+            start_time = now_time - 24 * 60 * 60 * 30
+            sensor_record_qs = SensorRecord.objects.filter(gateway_sub_device_id=sub_device_id,
+                                                           event_type=event_type,
+                                                           created_time__range=(start_time, now_time)). \
+                values('alarm', 'created_time').order_by('created_time')
+            if not sensor_record_qs.exists():
+                return record_dict
+
+            for sensor_record in sensor_record_qs:
+                created_time = time.strftime('%m/%d %H:%M %w', time.localtime(sensor_record['created_time']))
+                month = int(created_time[:2])
+                day = int(created_time[3:5])
+                date = str(month) + '/' + str(day)
+                alarm = float(sensor_record['alarm'])
+                # 组织数据,record_dict:{"1/1": [1.0, 2.0, 3.0], "1/2": [1.0, 2.0, 3.0]...}
+                if date in record_dict:
+                    record_dict[date].append(alarm)
+                else:
+                    record_dict[date] = [alarm]
+
+        return record_dict
+
     @staticmethod
     def records(request_dict, response):
         """
@@ -317,11 +363,11 @@ class GatewaySubDeviceView(View):
             if start_time and end_time:
                 sensor_record_qs = SensorRecord.objects.filter(gateway_sub_device_id=sub_device_id,
                                                                created_time__range=(start_time, end_time)). \
-                                       values('alarm', 'created_time').order_by('-created_time')[
+                                       values('alarm', 'event_type', 'created_time').order_by('-created_time')[
                                    (page - 1) * size:page * size]
             else:
                 sensor_record_qs = SensorRecord.objects.filter(gateway_sub_device_id=sub_device_id). \
-                                       values('alarm', 'created_time').order_by('-created_time')[
+                                       values('alarm', 'event_type', 'created_time').order_by('-created_time')[
                                    (page - 1) * size:page * size]
             if not sensor_record_qs.exists():
                 return response.json(0, [])
@@ -360,3 +406,182 @@ class GatewaySubDeviceView(View):
             return response.json(0, record_date_list)
         except Exception as e:
             return response.json(500, repr(e))
+
+    @staticmethod
+    def sensor_home_info(request_dict, response):
+        """
+        查询子设备首页信息
+        @param request_dict: 请求参数
+        @request_dict gatewaySubId: 子设备id
+        @param response: 响应对象
+        @return: response
+        """
+        sub_device_id = request_dict.get('gatewaySubId', None)
+        if not sub_device_id:
+            return response.json(444, {'error param': 'gatewaySubId'})
+
+        try:
+            sub_device_qs = GatewaySubDevice.objects.filter(id=sub_device_id).values('device_type', 'status',
+                                                                                     'is_tampered')
+            if not sub_device_qs.exists():
+                return response.json(173)
+            scene_count = SmartScene.objects.filter(sub_device_id=sub_device_id).count()
+            res = {
+                'scene_count': scene_count,
+                'status': sub_device_qs[0]['status']
+            }
+
+            device_type = sub_device_qs[0]['device_type']
+            # 门磁,烟雾,人体传感器返回拆动状态
+            if device_type == SENSOR_TYPE['door_magnet'] or device_type == SENSOR_TYPE['smoke_sensor'] or \
+                    device_type == SENSOR_TYPE['body_sensor']:
+                res['is_tampered'] = sub_device_qs[0]['is_tampered']
+            # 温湿度传感器返回温湿度数据
+            elif device_type == SENSOR_TYPE['tem_hum_sensor']:
+                tem_record_qs = SensorRecord.objects.filter(gateway_sub_device_id=sub_device_id,
+                                                            event_type=EVENT_TYPE['temperature']).order_by(
+                    '-created_time').values('alarm')[:1]
+                hum_record_qs = SensorRecord.objects.filter(gateway_sub_device_id=sub_device_id,
+                                                            event_type=EVENT_TYPE['humidity']).order_by(
+                    '-created_time').values('alarm')[:1]
+                temperature = tem_record_qs[0]['alarm'] if tem_record_qs.exists() else ''
+                humidity = hum_record_qs[0]['alarm'] if tem_record_qs.exists() else ''
+                res['temperature'] = temperature
+                res['humidity'] = humidity
+
+            return response.json(0, res)
+        except Exception as e:
+            return response.json(500, repr(e))
+
+    @staticmethod
+    def update_emergency_status(request_dict, response):
+        """
+        更新智能按钮紧急开关状态
+        @param request_dict: 请求参数
+        @request_dict gatewaySubId: 子设备id
+        @request_dict emergencyStatus: 紧急开关状态,0:关,1:开
+        @param response: 响应对象
+        @return: response
+        """
+        sub_device_id = request_dict.get('gatewaySubId', None)
+        emergency_status = request_dict.get('emergencyStatus', None)
+        if not all([sub_device_id, emergency_status]):
+            return response.json(444, {'error param': 'gatewaySubId or emergency_status'})
+
+        try:
+            emergency_status = int(emergency_status)
+            sub_device_qs = GatewaySubDevice.objects.filter(id=sub_device_id)
+            if not sub_device_qs.exists():
+                response.json(173)
+            with transaction.atomic():
+                # 更新智能按钮紧急开关状态
+                sub_device_qs.update(is_tampered=emergency_status)
+                # 获取序列号
+                sub_device_qs = sub_device_qs.values('device_id', 'src_addr', 'device__serial_number')
+                serial_number = sub_device_qs[0]['device__serial_number']
+                topic_name = SMART_SCENE_TOPIC.format(serial_number)
+                gateway_sub_device_qs = GatewaySubDevice.objects.filter(device_id=sub_device_qs[0]['device_id'],
+                                                                        device_type=SENSOR_TYPE['smart_button']).values(
+                    'src_addr')
+                sos_count = gateway_sub_device_qs.count()
+                sos_num = 1
+                for index, gateway_sub_device in enumerate(gateway_sub_device_qs):
+                    if sub_device_qs[0]['src_addr'] == gateway_sub_device['src_addr']:
+                        sos_num += index
+                # 通知设备修改sos状态
+                msg = {
+                    'sos_count': sos_count,  # 该网关下的智能按钮数量
+                    'sos_num': sos_num,  # 第几个按钮
+                    'sensor_src': int(sub_device_qs[0]['src_addr'], 16),
+                    'sos_select': emergency_status
+                }
+                success = CommonService.req_publish_mqtt_msg(serial_number, topic_name, msg, 0)
+                try:
+                    assert success
+                except AssertionError:
+                    return response.json(10044)
+                time.sleep(0.3)
+                # 如果打开紧急开关,关闭已开启的场景
+                if emergency_status == 1:
+                    smart_scene_qs = SmartScene.objects.filter(sub_device_id=sub_device_id, is_enable=True)
+                    if not smart_scene_qs.exists():
+                        return response.json(0)
+                    for smart_scene in smart_scene_qs:
+                        # 通知设备关闭场景
+                        msg = {
+                            'scene_id': smart_scene.id,
+                            'scene_status': 0
+                        }
+                        success = CommonService.req_publish_mqtt_msg(serial_number, topic_name, msg, 0)
+                        try:
+                            assert success
+                        except AssertionError:
+                            return response.json(10044)
+                        time.sleep(0.3)
+                    smart_scene_qs.update(is_enable=False)
+
+            return response.json(0)
+        except Exception as e:
+            return response.json(500, repr(e))
+
+    @staticmethod
+    def get_sensor_list(request_dict, response):
+        """
+        获取子设备信息
+        @param request_dict: 请求参数
+        @request_dict familyId: 家庭id
+        @param response: 响应对象
+        @return: response
+        """
+        family_id = request_dict.get('familyId', None)
+        room_id = request_dict.get('roomId', None)
+        if not family_id:
+            return response.json(444, {'error param': 'familyId'})
+
+        try:
+            family_room_device_qs = FamilyRoomDevice.objects.filter(Q(family_id=family_id), ~Q(sub_device=0)).values(
+                'sub_device', 'room_id').order_by('sort', '-device__data_joined')
+            if room_id:
+                family_room_device_qs = family_room_device_qs.filter(room_id=room_id)
+            device_list = []
+            for item in family_room_device_qs:
+                room_qs = FamilyRoom.objects.filter(id=item['room_id']).values('name')
+                room_name = room_qs[0]['name'] if room_qs.exists() else ''
+                device_qs = GatewaySubDevice.objects.filter(id=item['sub_device']).values('id', 'nickname',
+                                                                                          'device_type', 'src_addr',
+                                                                                          'status', 'created_time')
+                if device_qs.exists():
+                    res = {
+                        'gatewaySubId': device_qs[0]['id'],
+                        'nickName': device_qs[0]['nickname'],
+                        'deviceType': device_qs[0]['device_type'],
+                        'srcAddr': device_qs[0]['src_addr'],
+                        'status': device_qs[0]['status'],
+                        'createdTime': device_qs[0]['created_time'],
+                        'roomName': room_name
+                    }
+                    device_list.append(res)
+            return response.json(0, device_list)
+        except Exception as e:
+            return response.json(500, repr(e))
+
+#
+#                   ___====-_  _-====___
+#             _--^^^#####//      \\#####^^^--_
+#          _-^##########// (    ) \\##########^-_
+#         -############//  |\^^/|  \\############-
+#       _/############//   (@::@)   \\############\_
+#      /#############((     \\//     ))#############\
+#     -###############\\    (oo)    //###############-
+#    -#################\\  / VV \  //#################-
+#   -###################\\/      \//###################-
+#  _#/|##########/\######(   /\   )######/\##########|\#_
+#  |/ |#/\#/\#/\/  \#/\##\  |  |  /##/\#/  \/\#/\#/\#| \|
+#  `  |/  V  V  `   V  \#\| |  | |/#/  V   '  V  V  \|  '
+#     `   `  `      `   / | |  | | \   '      '  '   '
+#                      (  | |  | |  )
+#                     __\ | |  | | /__
+#                    (vvv(VVV)(VVV)vvv)
+#                         神兽保佑
+#                        代码无BUG!
+#

+ 129 - 26
Controller/TestApi.py

@@ -12,51 +12,38 @@
 @Contact: chanjunkai@163.com
 """
 import botocore
-from django.db import transaction
-from django.views.generic.base import View
-import os
-
+from botocore import client
 from Controller.DeviceConfirmRegion import Device_Region
+from Object.AWS.AmazonS3Util import AmazonS3Util
 
 '''
 http://192.168.136.40:8077/Test
 '''
 import json
-import math
 import time
 import urllib
-import datetime
 from Object.AliPayObject import AliPayObject
-import logging
 import boto3
 from boto3.session import Session
-from botocore.exceptions import ClientError
 import oss2
 import paypalrestsdk
 import logging
-import requests
-import hashlib
-import hmac
 from aliyunsdkcore import client
 from aliyunsdksts.request.v20150401 import AssumeRoleRequest
-from django.http import JsonResponse, HttpResponseRedirect, HttpResponse
+from django.http import JsonResponse, HttpResponse
 from django.utils.decorators import method_decorator
 from django.views.decorators.csrf import csrf_exempt
 from django.views.generic.base import View
-from Object.RedisObject import RedisObject
-from django.contrib.auth.hashers import make_password, check_password  # 对密码加密模块
-from Ansjer.config import OSS_STS_ACCESS_KEY, OSS_STS_ACCESS_SECRET, OSS_ROLE_ARN, SERVER_DOMAIN, PAYPAL_CRD, \
-    SERVER_DOMAIN_SSL, AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, SERVER_TYPE
-from Model.models import Device_Info, Order_Model, Store_Meal, VodHlsModel, OssCrdModel, UID_Bucket, CompanySerialModel, \
-    SerialNumberModel, CompanyModel, VPGModel, Unused_Uid_Meal, StsCrdModel, ExperienceContextModel, DeviceLogModel
+from django.contrib.auth.hashers import make_password  # 对密码加密模块
+from Ansjer.config import OSS_STS_ACCESS_KEY, OSS_STS_ACCESS_SECRET, OSS_ROLE_ARN, AWS_ACCESS_KEY_ID, \
+    AWS_SECRET_ACCESS_KEY, SERVER_TYPE, AWS_SES_ACCESS_REGION
+from Model.models import Order_Model, Store_Meal, VodHlsModel, OssCrdModel, StsCrdModel, DeviceLogModel
 from Object.ResponseObject import ResponseObject
 from Object.TokenObject import TokenObject
-from Object.UidTokenObject import UidTokenObject
 from Service.CommonService import CommonService
-from Service.ModelService import ModelService
 from Object.m3u8generate import PlaylistGenerator
-from Model.models import Device_User, Device_Info, UID_Bucket, UID_Preview, UidSetModel, UidPushModel
-from Ansjer.config import PAYPAL_CRD, SERVER_DOMAIN, SERVER_DOMAIN_SSL, PAYPAL_WEB_HOOK_ID
+from Model.models import Device_Info, UID_Bucket, UID_Preview, UidSetModel
+from Ansjer.config import SERVER_DOMAIN_SSL
 
 SERVER_DOMAIN = 'http://test.dvema.com/'
 ACCESS_KEY = "AKIA2E67UIMD3CYTIWPA"
@@ -142,9 +129,124 @@ class testView(View):
             return self.do_comb(request_dict, response)
         elif operation == 'count_ts':
             return self.count_ts(request_dict, response)
+        elif operation == 'upload-s3':
+            return self.file_upload_s3(request, request_dict, response)
+        elif operation == 'v2/upload-s3':
+            return self.file_upload_s3_v2(request, request_dict, response)
+        elif operation == 'download-s3':
+            return self.file_download_s3(request_dict, response)
+        elif operation == 'acl-put':
+            return self.s3_acl_put(request_dict, response)
+        elif operation == 's3-object-delete':
+            return self.object_delete(request_dict, response)
+        elif operation == 'head-bucket':
+            return self.head_bucket(request_dict, response)
         else:
             return 123
 
+    @classmethod
+    def head_bucket(cls, request_dict, response):
+        bucket_name = request_dict.get('bucket', None)
+        s3 = AmazonS3Util('AKIA2E67UIMD45Y3HL53', 'ckYLg4Lo9ZXJIcJEAKkzf2rWvs8Xth1FCjqiAqUw', 'us-east-1')
+        s3.bucket_exists(bucket_name)
+        return response.json(0)
+
+    @classmethod
+    def file_upload_s3(cls, request, request_dict, response):
+        file = request.FILES.get('file', None)
+        file_name = file.name
+        file_name = 'app/images/{}'.format(file_name)
+        cls.upload_s3(file, file_name)
+        return response.json(0)
+
+    @classmethod
+    def file_upload_s3_v2(cls, request, request_dict, response):
+        """
+        'private' | 'public-read' | 'public-read-write' | 'authenticated-read'
+        """
+        file = request.FILES.get('file', None)
+        file_name = file.name
+        # S3下文件夹路径+文件名 组成对象key
+        file_key = 'app/images/{}'.format(file_name)
+        s3 = AmazonS3Util(AWS_ACCESS_KEY_ID[1], AWS_SECRET_ACCESS_KEY[1], AWS_SES_ACCESS_REGION)
+        # 存储桶
+        bucket = 'ansjerfilemanager'
+        s3.upload_file_obj(bucket, file_key, file, {'ContentType': file.content_type, 'ACL': 'public-read'})
+        return response.json(0)
+
+    @classmethod
+    def object_delete(cls, request_dict, response):
+        file_name = request_dict.get('key', None)
+        file_key = 'app/images/{}'.format(file_name)
+        s3 = AmazonS3Util('AKIA2E67UIMD45Y3HL53', 'ckYLg4Lo9ZXJIcJEAKkzf2rWvs8Xth1FCjqiAqUw', 'us-east-1')
+        bucket = "ansjerfilemanager"
+        s3.delete_obj(bucket, file_key)
+        return response.json(0)
+
+    @staticmethod
+    def upload_s3(data, upload_path):
+        """
+        上传对象到对应存储桶
+        @param data:
+        @param upload_path:
+        @return:
+        """
+        try:
+            aws_key = "AKIA2E67UIMD45Y3HL53"  # 【你的 aws_access_key】
+            aws_secret = "ckYLg4Lo9ZXJIcJEAKkzf2rWvs8Xth1FCjqiAqUw"  # 【你的 aws_secret_key】
+            session = Session(aws_access_key_id=aws_key,
+                              aws_secret_access_key=aws_secret,
+                              region_name="us-east-1")
+            s3 = session.resource("s3")
+            # client = session.client("s3")
+            bucket = "ansjerfilemanager"  # 【你 bucket 的名字】 # 首先需要保.证 s3 上已经存在该存储桶,否则报错
+            # upload_key = "test"
+            s3.Bucket(bucket).put_object(Key=upload_path, Body=data)
+            return True
+        except Exception as e:
+            print(repr(e))
+            return False
+
+    @classmethod
+    def s3_acl_put(cls, request_dict, response):
+        """
+        S3通过存储桶对象设置Acl权限
+        @param request_dict:
+        @param response:
+        @return:
+        """
+        try:
+            key = request_dict.get('key', None)
+            aws_key = "AKIA2E67UIMD45Y3HL53"  # 【你的 aws_access_key】
+            aws_secret = "ckYLg4Lo9ZXJIcJEAKkzf2rWvs8Xth1FCjqiAqUw"  # 【你的 aws_secret_key】
+            session = Session(aws_access_key_id=aws_key,
+                              aws_secret_access_key=aws_secret,
+                              region_name="us-east-1")
+            s3 = session.resource("s3")
+            # client = session.client("s3")
+            bucket = "ansjerfilemanager"  # 【你 bucket 的名字】 # 首先需要保.证 s3 上已经存在该存储桶,否则报错
+            # upload_key = "test"
+            obj = s3.Object(bucket, key)
+            obj.Acl().put(ACL='public-read')
+            return response.json(0)
+        except Exception as e:
+            print(repr(e))
+            return False
+
+    @classmethod
+    def file_download_s3(cls, request_dict, response):
+        """
+        S3通过签名获取对象URL
+        @param request_dict:
+        @param response:
+        @return:
+        """
+        key = request_dict.get('key', None)
+        s3_client = AmazonS3Util('AKIA2E67UIMD45Y3HL53', 'ckYLg4Lo9ZXJIcJEAKkzf2rWvs8Xth1FCjqiAqUw', 'us-east-1')
+        bucket = "ansjerfilemanager"
+        response_url = s3_client.generate_file_obj_url(bucket, key)
+        return response.json(0, response_url)
+
     def do_comb(self, request_dict, response):
         import itertools
         list1 = [1, 2, 3, 4]
@@ -164,7 +266,6 @@ class testView(View):
         return HttpResponse(json.dumps(list3))
 
     def findPaypalOrder(self, request_dict, response):
-        from paypalrestsdk import Order, ResourceNotFound
         PAYPAL_CRD = {
             "mode": "sandbox",  # sandbox or live
             "client_id": "AVLoQVq3xHZ6FrF4mxHwlCPgVBAw4Fw5RtMkuxmYd23SkUTIY643n2g3KdK-Al8wV05I28lza5uoQbAA",
@@ -875,6 +976,8 @@ class testView(View):
                 sumSec += (fg >> shift) & 0xf
         size = 0
         return HttpResponse(
-            "{year}年{month}月 </br>上传的TS总数:{sumTs} </br> 总秒数:{sumSec} </br> 总大小:{size}GB (1秒约等150KB计算)".format(year=year, month=month,
-                                                                                           sumTs=sumTs, sumSec=sumSec,
-                                                                                           size=size))
+            "{year}年{month}月 </br>上传的TS总数:{sumTs} </br> 总秒数:{sumSec} </br> 总大小:{size}GB (1秒约等150KB计算)".format(year=year,
+                                                                                                              month=month,
+                                                                                                              sumTs=sumTs,
+                                                                                                              sumSec=sumSec,
+                                                                                                              size=size))

+ 95 - 81
Controller/UserController.py

@@ -11,26 +11,34 @@
 @file: UserController.py
 @Contact: chanjunkai@163.com
 """
+import base64
 import datetime
-import traceback
-import time
 import logging
+import random
 import threading
+import time
+import traceback
+from io import BytesIO
+
 import jwt
+import requests
 import simplejson
 import simplejson as json
-import requests
+from PIL import Image, ImageDraw, ImageFont
 from django.contrib.auth.hashers import make_password, check_password  # 对密码加密模块
 from django.db.models import Q
 from django.http import HttpResponseRedirect
+from django.shortcuts import HttpResponse
 from django.utils.decorators import method_decorator
 from django.utils.timezone import utc
 from django.views.decorators.csrf import csrf_exempt
 from django.views.generic import TemplateView
+from django.views.generic import View
 from jwt.algorithms import RSAAlgorithm
 from ratelimit.decorators import ratelimit
 
 from Ansjer.config import AuthCode_Expire, SERVER_DOMAIN, APNS_CONFIG, JPUSH_CONFIG, FCM_CONFIG, TUTK_PUSH_DOMAIN
+from Ansjer.config import BASE_DIR
 from Controller.CheckUserData import DataValid, date_handler, RandomStr
 from Model.models import Device_User, Role, UidPushModel, UserOauth2Model, UserExModel, Device_Info, UidSetModel, \
     UserAppFrequencyModel, CountryIPModel, CountryModel, UidChannelSetModel, Order_Model, UID_Bucket, Unused_Uid_Meal, \
@@ -40,17 +48,10 @@ from Object.AliSmsObject import AliSmsObject
 from Object.RedisObject import RedisObject
 from Object.ResponseObject import ResponseObject
 from Object.TokenObject import TokenObject
+from Object.UVerifyObject import UVerifyObject
 from Service.CommonService import CommonService
 from Service.ModelService import ModelService
 from Service.TemplateService import TemplateService
-from django.views.generic import View
-import base64
-import random
-from io import BytesIO
-from PIL import Image, ImageDraw, ImageFont
-from django.shortcuts import HttpResponse
-from Ansjer.config import BASE_DIR
-from Object.UVerifyObject import UVerifyObject
 
 
 # 获取验证码
@@ -292,6 +293,7 @@ class registerView(TemplateView):
         else:
             return response.json(109)
 
+
 # 登出
 class LogoutView(TemplateView):
     @method_decorator(csrf_exempt)
@@ -312,24 +314,19 @@ class LogoutView(TemplateView):
         response = ResponseObject()
         token = request_dict.get('token')
         tko = TokenObject(token)
-        if tko.code == 0:
-            Device_User.objects.filter(userID=tko.userID).update(online=False)
-
-            redisObj = RedisObject(db=3)
-            redisObj.del_data(key=tko.userID)
-            m_code = request_dict.get('m_code', None)
-            if m_code:
-                userID = tko.userID
-                try:
-                    UidPushModel.objects.filter(userID_id=userID, m_code=m_code).delete()
-                except Exception as e:
-                    pass
-                else:
-                    pass
-            return response.json(0)
-        else:
+        if tko.code != 0:
             return response.json(tko.code)
 
+        Device_User.objects.filter(userID=tko.userID).update(online=False)
+        redisObj = RedisObject(db=3)
+        redisObj.del_data(key=tko.userID)
+        m_code = request_dict.get('m_code', None)
+        if m_code:
+            userID = tko.userID
+            UidPushModel.objects.filter(userID_id=userID, m_code=m_code).delete()
+            GatewayPush.objects.filter(user_id=userID, m_code=m_code).update(logout=True)
+        return response.json(0)
+
 
 # 修改密码
 class ChangePwdView(TemplateView):
@@ -711,7 +708,7 @@ class refreshTokenViewV3(TemplateView):
             userID = tko.userID
             tko.lang = lang
 
-            if password:     # 检验密码
+            if password:  # 检验密码
                 password = password.strip()
                 # 解密
                 for i in range(1, 4):
@@ -905,8 +902,8 @@ class v2authCodeView(TemplateView):
             msg = res["Message"]
             if code == "isv.MOBILE_NUMBER_ILLEGAL":
                 if response.lang == "cn":
-                    msg = phone+"非法手机"
-            return response.json(10,msg)
+                    msg = phone + "非法手机"
+            return response.json(10, msg)
 
     def phoneCodeV2(self, country_code, phone, response, sign_name):
         dataValid = DataValid()
@@ -1977,28 +1974,28 @@ class v3LoginView(TemplateView):
         else:
             data_valid = DataValid()
             if data_valid.email_validate(username):
-                return self.do_email_login(username, password, response, subscribe, number)
+                return self.do_email_login(username, password, response, subscribe, number, request_dict)
             elif data_valid.mobile_validate(username):
-                return self.do_phone_login(username, password, response, subscribe, number)
+                return self.do_phone_login(username, password, response, subscribe, number, request_dict)
             elif data_valid.name_validate(username):
-                return self.do_name_login(username, password, response, subscribe, number)
+                return self.do_name_login(username, password, response, subscribe, number, request_dict)
             else:
                 return response.json(107)
 
-    def do_email_login(self, email, password, response, subscribe, number):
+    def do_email_login(self, email, password, response, subscribe, number, request_dict):
         user_qs = Device_User.objects.filter(Q(username=email) | Q(userEmail=email))
-        return self.valid_login(user_qs, password, response, subscribe, number)
+        return self.valid_login(user_qs, password, response, subscribe, number, request_dict)
 
-    def do_phone_login(self, phone, password, response, subscribe, number):
+    def do_phone_login(self, phone, password, response, subscribe, number, request_dict):
         user_qs = Device_User.objects.filter(Q(phone=phone) | Q(username=phone), is_active=True, user_isValid=True)
-        return self.valid_login(user_qs, password, response, subscribe, number)
+        return self.valid_login(user_qs, password, response, subscribe, number, request_dict)
 
-    def do_name_login(self, username, password, response, subscribe, number):
+    def do_name_login(self, username, password, response, subscribe, number, request_dict):
         user_qs = Device_User.objects.filter(Q(username=username) | Q(phone=username) | Q(userEmail=username),
                                              is_active=True, user_isValid=True)
-        return self.valid_login(user_qs, password, response, subscribe, number)
+        return self.valid_login(user_qs, password, response, subscribe, number, request_dict)
 
-    def valid_login(self, user_qs, password, response, subscribe, number):
+    def valid_login(self, user_qs, password, response, subscribe, number, request_dict):
         if not user_qs.exists():
             return response.json(104)
         # users = user_qs.values('role__rid', 'role__roleName', 'userID', 'role', 'NickName', 'username', 'userEmail',
@@ -2007,9 +2004,11 @@ class v3LoginView(TemplateView):
             user_qs.update(subscribe_email=subscribe)
 
         users = user_qs.values('role__rid', 'role__roleName', 'userID', 'NickName', 'username', 'userEmail',
-                               'phone', 'password', 'userIconPath', 'fingerprint_enable', 'fingerprint_key', 'subscribe_email')[0]
+                               'phone', 'password', 'userIconPath', 'fingerprint_enable', 'fingerprint_key',
+                               'subscribe_email')[0]
         if not check_password(password, users['password']):
             return response.json(111)
+
         userID = users['userID']
         tko = TokenObject()
         res = tko.generate(
@@ -2019,36 +2018,49 @@ class v3LoginView(TemplateView):
         if oauth_qs.exists():
             auth_type = oauth_qs[0].authType
 
+        if tko.code != 0:
+            return response.json(tko.code)
 
-        if tko.code == 0:
-            now_time = datetime.datetime.utcnow().replace(tzinfo=utc).astimezone(utc)
-            if not number:
-                user_qs.update(last_login=now_time, language=response.lang)
+        # 网关推送新增内容
+        app_bundle_id = request_dict.get('appBundleId', None)
+        app_type = request_dict.get('appType', None)
+        push_type = request_dict.get('pushType', None)
+        token_val = request_dict.get('tokenVal', None)
+        m_code = request_dict.get('mCode', None)
+        lang = request_dict.get('language', 'en')
+        tz = request_dict.get('tz', None)
+        if all([app_bundle_id, app_type, push_type, token_val, m_code, tz]):
+            gateway_push_qs = GatewayPush.objects.filter(user_id=userID, m_code=m_code)
+            if gateway_push_qs.exists():
+                gateway_push_qs.update(token_val=token_val, logout=False)
             else:
-                user_qs.update(last_login=now_time, language=response.lang, region_country=number)
+                GatewayPush.objects.create(user_id=userID, app_bundle_id=app_bundle_id, app_type=app_type,
+                                           push_type=push_type, token_val=token_val, m_code=m_code, lang=lang, tz=tz)
 
-            res['rid'] = users['role__rid']
-            res['roleName'] = users['role__roleName']
-            res['permList'] = ModelService.own_permission(userID)
-            res['userID'] = userID
-            # 昵称,邮箱,电话,刷新,头像
-            userIconPath = str(users['userIconPath'])
-            if userIconPath and userIconPath.find('static/') != -1:
-                userIconPath = userIconPath.replace('static/', '').replace('\\', '/')
-                res['userIconUrl'] = SERVER_DOMAIN + 'account/getAvatar/' + userIconPath
-            else:
-                res['userIconUrl'] = ''
-            res['NickName'] = users['NickName'] if users['NickName'] is not None else ''
-            res['username'] = users['username'] if users['username'] is not None else ''
-            res['userEmail'] = users['userEmail'] if users['userEmail'] is not None else ''
-            res['phone'] = users['phone'] if users['phone'] is not None else ''
-            # res['fingerprint_enable'] = users['fingerprint_enable']
-            # res['fingerprint_key'] = CommonService.encode_data(content=users['fingerprint_key'], start=2)
-            res['authType'] = auth_type
-            res['subscribe_email'] = users['subscribe_email'] if users['subscribe_email'] is not None else ''
-            return response.json(0, res)
+        now_time = datetime.datetime.utcnow().replace(tzinfo=utc).astimezone(utc)
+        if not number:
+            user_qs.update(last_login=now_time, language=response.lang)
         else:
-            return response.json(tko.code)
+            user_qs.update(last_login=now_time, language=response.lang, region_country=number)
+
+        res['rid'] = users['role__rid']
+        res['roleName'] = users['role__roleName']
+        res['permList'] = ModelService.own_permission(userID)
+        res['userID'] = userID
+        # 昵称,邮箱,电话,刷新,头像
+        userIconPath = str(users['userIconPath'])
+        if userIconPath and userIconPath.find('static/') != -1:
+            userIconPath = userIconPath.replace('static/', '').replace('\\', '/')
+            res['userIconUrl'] = SERVER_DOMAIN + 'account/getAvatar/' + userIconPath
+        else:
+            res['userIconUrl'] = ''
+        res['NickName'] = users['NickName'] if users['NickName'] is not None else ''
+        res['username'] = users['username'] if users['username'] is not None else ''
+        res['userEmail'] = users['userEmail'] if users['userEmail'] is not None else ''
+        res['phone'] = users['phone'] if users['phone'] is not None else ''
+        res['authType'] = auth_type
+        res['subscribe_email'] = users['subscribe_email'] if users['subscribe_email'] is not None else ''
+        return response.json(0, res)
 
 
 # 一键登录接口
@@ -2080,7 +2092,8 @@ class oneClickLoginView(TemplateView):
             if not phone:
                 return response.json(102)
 
-            user_qs = Device_User.objects.filter(phone=phone).values('userID', 'username', 'NickName', 'phone', 'password')
+            user_qs = Device_User.objects.filter(phone=phone).values('userID', 'username', 'NickName', 'phone',
+                                                                     'password')
             # 用户已存在的响应
             if user_qs.exists():
                 tokenObj = TokenObject()
@@ -3096,7 +3109,8 @@ class alexaUidView(TemplateView):
                 uid_list.append(UID)
                 uid_dict[UID] = {'nick': uid_q['NickName'], 'password': uid_q['View_Password']}
 
-            us_qs = UidSetModel.objects.filter(uid__in=uid_list, is_alexa=1).values('id', 'uid', 'region_alexa', 'channel')
+            us_qs = UidSetModel.objects.filter(uid__in=uid_list, is_alexa=1).values('id', 'uid', 'region_alexa',
+                                                                                    'channel')
             if not us_qs.exists():
                 return response.json(173)
             # uid,password,region的列表
@@ -3111,7 +3125,8 @@ class alexaUidView(TemplateView):
 
                 # 多通道设备获取通道名
                 if channel > 1:
-                    uid_channel_set_qs = UidChannelSetModel.objects.filter(uid_id=us['id']).values('channel', 'channel_name')
+                    uid_channel_set_qs = UidChannelSetModel.objects.filter(uid_id=us['id']).values('channel',
+                                                                                                   'channel_name')
                     if uid_channel_set_qs.exists():
                         # DVR设备名为 UidChannelSetModel 的 channel_name
                         for uid_channel_set in uid_channel_set_qs:
@@ -3128,6 +3143,7 @@ class alexaUidView(TemplateView):
         except Exception as e:
             return response.json(500, repr(e))
 
+
 # 登出
 class V2LogoutView(TemplateView):
     @method_decorator(csrf_exempt)
@@ -3634,7 +3650,6 @@ class v3LoginByCodeView(View):
         if oauth_qs.exists():
             auth_type = oauth_qs[0].authType
 
-
         if tko.code == 0:
             now_time = datetime.datetime.utcnow().replace(tzinfo=utc).astimezone(utc)
             user_qs.update(last_login=now_time, language=response.lang)
@@ -4089,6 +4104,7 @@ def updateUserCountry(request):
     response = ResponseObject()
     return response.json(0)
 
+
 def confirmRegion(request):
     response = ResponseObject()
     request.encoding = 'utf-8'
@@ -4099,17 +4115,17 @@ def confirmRegion(request):
     number = request.POST.get('number', None)
     selectRegion = CountryModel.objects.filter(number=number).values('region__api')
     if not selectRegion.exists():
-        return response.json(0,{"request_url":"https://www.dvema.com"})
+        return response.json(0, {"request_url": "https://www.dvema.com"})
     else:
-        return response.json(0,{"request_url":selectRegion[0]['region__api']})
+        return response.json(0, {"request_url": selectRegion[0]['region__api']})
 
 
 def deleteAccount(request):
     response = ResponseObject()
     request.encoding = 'utf-8'
-    #test
-    token = request.POST.get('token',None)
-    password = request.POST.get('userPwd',None)
+    # test
+    token = request.POST.get('token', None)
+    password = request.POST.get('userPwd', None)
     try:
         for i in range(1, 4):
             if i == 1:
@@ -4155,8 +4171,8 @@ def deleteAccount(request):
         if hasDevices.exists():
             return response.json(10047)
 
-        orderUserIds = Order_Model.objects.filter(userID=userID,status=1).values_list('UID').distinct().order_by("UID")
-        hadUseSevice = UID_Bucket.objects.filter(uid__in=orderUserIds,use_status=1)
+        orderUserIds = Order_Model.objects.filter(userID=userID, status=1).values_list('UID').distinct().order_by("UID")
+        hadUseSevice = UID_Bucket.objects.filter(uid__in=orderUserIds, use_status=1)
         if hadUseSevice.exists():
             return response.json(10046)
 
@@ -4203,7 +4219,7 @@ class InitUserInformationView(View):
             now_time = int(time.time())
             if user_ex_qs.exists():
                 update = {
-                    'appBundleId':appBundleId,
+                    'appBundleId': appBundleId,
                     'updTime': now_time
                 }
                 user_ex_qs.update(**update)
@@ -4214,5 +4230,3 @@ class InitUserInformationView(View):
             return response.json(0)
         else:
             return response.json(444)
-
-

+ 0 - 17
Model/models.py

@@ -1768,23 +1768,6 @@ class ProcessInfoLogsModel(models.Model):
         verbose_name_plural = verbose_name
 
 
-class EquipmentLogModel(models.Model):
-    id = models.AutoField(primary_key=True)
-    user = models.CharField(blank=False, max_length=32, db_index=True, verbose_name=u'操作用户')
-    uid = models.CharField(default='', blank=True, max_length=32, verbose_name=u'设备uid')
-    equipmentid = models.CharField(blank=False, max_length=100, db_index=True, verbose_name=u'设备主键id')
-    NickName = models.CharField(blank=True, max_length=32, verbose_name=u'设备名称')
-    ip = models.CharField(max_length=100, default='', db_index=True, blank=True, verbose_name=u'访问ip地址')
-    time = models.DateTimeField(null=True, blank=True, db_index=True, verbose_name=u'访问时间')
-    operatingcontent = models.TextField(blank=True, default='', verbose_name=u'操作内容')
-    url = models.CharField(max_length=150, default='', blank=True, verbose_name=u'访问路径')
-
-    class Meta:
-        db_table = 'equipment_log'
-        verbose_name = '设备日志表'
-        verbose_name_plural = verbose_name
-
-
 class UserModel(models.Model):
     id = models.AutoField(primary_key=True)
     username = models.CharField(unique=True, max_length=128, null=False, verbose_name='用户名')

+ 112 - 0
Object/AWS/AmazonS3Util.py

@@ -0,0 +1,112 @@
+# -*- encoding: utf-8 -*-
+"""
+@File    : AmazonS3Util.py
+@Time    : 2022/8/11 14:00
+@Author  : stephen
+@Email   : zhangdongming@asj6.wecom.work
+@Software: PyCharm
+"""
+import logging
+import traceback
+
+import boto3
+import botocore
+from boto3.session import Session
+from botocore import client
+from botocore.exceptions import ClientError
+
+logger = logging.getLogger('info')
+
+
+class AmazonS3Util:
+    def __init__(self, aws_access_key_id, secret_access_key, region_name):
+        self.access_id = aws_access_key_id
+        self.access_secret = secret_access_key
+        self.region_name = region_name
+        session = Session(
+            aws_access_key_id=aws_access_key_id,
+            aws_secret_access_key=secret_access_key,
+            region_name=region_name
+        )
+        self.client_conn = boto3.client(
+            's3',
+            aws_access_key_id=aws_access_key_id,
+            aws_secret_access_key=secret_access_key,
+            config=botocore.client.Config(signature_version='s3v4'),
+            region_name=region_name
+        )
+        self.session_conn = session.resource('s3')
+
+    def upload_file_obj(self, bucket, file_key, file_obj, extra_args=None):
+        """
+        对象上传至S3存储桶
+        https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/s3.html#S3.Object.upload_file
+        @param bucket: 存储桶名称-必须
+        @param file_key: 需要上传文件路径+文件名称
+        @param file_obj: 文件对象
+        @param extra_args: 额外参数 如ACL配置
+        @return: 当上传成功时为True;否则,False
+        """
+        try:
+            session = self.session_conn
+            bucket = session.Bucket(bucket)
+            obj = bucket.Object(file_key)
+            obj.upload_fileobj(file_obj, ExtraArgs=extra_args)
+            return True
+        except Exception as e:
+            print(e.args)
+            ex = traceback.format_exc()
+            print('具体错误{}'.format(ex))
+            return False
+
+    def generate_file_obj_url(self, bucket, file_key):
+        """
+        生成对象URL
+        https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/s3.html#S3.Client.generate_presigned_url
+        @param bucket: 存储桶名称
+        @param file_key: 文件名称
+        @return: url
+        """
+        response_url = self.client_conn.generate_presigned_url(
+            ClientMethod='get_object',
+            Params={
+                'Bucket': bucket,
+                'Key': file_key
+            },
+            ExpiresIn=3600
+        )
+        return response_url
+
+    def delete_obj(self, bucket, file_key):
+        """
+        删除对象
+        https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/s3.html#S3.Object.delete
+        @param bucket: 存储桶
+        @param file_key: 文件名称
+        @return: 当删除成功时为True;否则,False
+        """
+        try:
+            bucket = self.session_conn.Bucket(bucket)
+            obj = bucket.Object(file_key)
+            obj.delete()
+            return True
+        except Exception as e:
+            print(e.args)
+            ex = traceback.format_exc()
+            print('具体错误{}'.format(ex))
+            return False
+
+    def bucket_exists(self, bucket_name):
+        """
+        判断桶是否存在,是否有访问权限
+        @return: 当bucket存在时为True;否则,假的
+        """
+        try:
+            self.client_conn.head_bucket(Bucket=bucket_name)
+            logger.info("存储桶 {} 存在.".format(bucket_name))
+            exists = True
+        except ClientError:
+            logger.warning(
+                "存储桶 {} 不存在,或者你没有权限.".format(bucket_name))
+            exists = False
+        return exists

+ 1 - 0
Object/LogsObject.py

@@ -124,6 +124,7 @@ class LogsObject(object):
             119: '二维码过期',
             120: '验证码过期',
             121: '验证码错了!',
+            172: '条件已存在',
             173: '数据不存在!',
             174: '数据已存在!',
             176: '删除错误',

+ 6 - 2
Object/ResponseObject.py

@@ -43,6 +43,7 @@ class ResponseObject(object):
             177: 'Update error',
             178: 'ADD error',
             179: 'Nickname repeated',
+            180: 'Smart button scene trigger conditions cannot be repeated',
             201: 'You can only add 3 custom voice at most',
             306: 'The link has expired!',
             309: 'Please ReLogin! errmsg token',
@@ -100,7 +101,7 @@ class ResponseObject(object):
             10041: 'This device has purchased a domestic cloud storage package, and cannot purchase a foreign cloud storage package',
             10042: 'The device has registered a certificate',
             10043: 'The device does not registered a certificate',
-            10044: 'Request to publish MQTT topic message failed',
+            10044: 'Failed to publish MQTT message',
             10045: 'Already the latest version',
             10046: 'Sorry, users who have activated cloud storage packages do not support logout at the moment, please contact customer service',
             10047: 'Please delete all devices under your account first',
@@ -114,6 +115,7 @@ class ResponseObject(object):
             10055: 'The AI does not recognize any labels',
             10056: 'The device has enabled automatic renewal of cloud storage package and cannot be transferred for the time being',
             10057: "Can't delete",
+            10058: 'Default family cannot be deleted'
         }
         data_cn = {
             0: '成功',
@@ -150,6 +152,7 @@ class ResponseObject(object):
             177: '更新错误',
             178: '增加错误',
             179: '名称不能重复',
+            180: '智能按钮场景触发条件不能重复',
             201: '最多只能添加3条自定义语音',
             306: '链接已超过有效期!',
             309: '请重新登录!',
@@ -207,7 +210,7 @@ class ResponseObject(object):
             10041: '此设备已购买过国内云存套餐,无法购买国外云存套餐',
             10042: '此设备已注册证书',
             10043: '此设备没有注册证书',
-            10044: '请求发布MQTT主题消息失败',
+            10044: '发布MQTT消息失败',
             10045: '当前为最新版本',
             10046: '已开通云存的用户,暂不支持注销,请联系客服',
             10047: '请先删除您当前帐户下的所有设备',
@@ -221,6 +224,7 @@ class ResponseObject(object):
             10055: 'AI没有识别到任何标签',
             10056: '该设备已开通云存套餐自动续费,暂时无法转移',
             10057: '不能删除',
+            10058: '默认家庭不能删除'
         }
         if self.lang == 'cn':
             msg = data_cn

+ 29 - 5
Service/CommonService.py

@@ -18,6 +18,8 @@ from pyipip import IPIPDatabase
 from Ansjer.config import BASE_DIR, SERVER_DOMAIN_SSL, CONFIG_INFO, CONFIG_TEST, CONFIG_CN
 from Controller.CheckUserData import RandomStr
 from Model.models import iotdeviceInfoModel, Device_Info, CountryModel, RegionModel, UIDModel
+from Object.ResponseObject import ResponseObject
+from Object.TokenObject import TokenObject
 
 
 class CommonService:
@@ -475,21 +477,27 @@ class CommonService:
             return False
 
     @staticmethod
-    def req_publish_mqtt_msg(thing_name, topic_name, msg):
+    def req_publish_mqtt_msg(identification_code, topic_name, msg, qos=1):
         """
         通用发布MQTT消息函数
-        @param thing_name: 物品名
+        @param identification_code: 标识码
         @param topic_name: 主题名
         @param msg: 消息内容
+        @param qos: mqtt qos等级
         @return: boolean
         """
-        if not all([thing_name, topic_name, msg]):
+        if not all([identification_code, topic_name]):
             return False
 
+        if identification_code.endswith('11L'):
+            thing_name = 'LC_' + identification_code
+        else:
+            thing_name = 'Ansjer_Device_' + identification_code
+
         try:
             # 获取数据组织将要请求的url
             iot = iotdeviceInfoModel.objects.filter(
-                thing_name__icontains=thing_name).values(
+                thing_name=thing_name).values(
                 'endpoint', 'token_iot_number')
             if not iot.exists():
                 return False
@@ -499,7 +507,7 @@ class CommonService:
             # api doc: https://docs.aws.amazon.com/zh_cn/iot/latest/developerguide/http.html
             # url: https://IoT_data_endpoint/topics/url_encoded_topic_name?qos=1
             # post请求url发布MQTT消息
-            url = 'https://{}/topics/{}'.format(endpoint, topic_name)
+            url = 'https://{}/topics/{}?qos={}'.format(endpoint, topic_name, qos)
             authorizer_name = 'Ansjer_Iot_Auth'
             signature = CommonService.rsa_sign(Token)  # Token签名
             headers = {
@@ -635,3 +643,19 @@ GCqvlyw5dfxNA+EtxNE2wCW/LW7ENJlACgcfgPlBZtpLheWoZB/maw4=
                 region_qs = RegionModel.objects.filter(continent_code='NA').values("id")
                 region_id = region_qs[0]['id']
         return region_id
+
+    @staticmethod
+    def verify_token_get_user_id(request_dict, request):
+        """
+        认证token,获取user id
+        @param request_dict: 请求参数
+        @param request: 请求体
+        @return: token_obj.code, token_obj.userID, response
+        """
+        try:
+            token_obj = TokenObject(request.META.get('HTTP_AUTHORIZATION'))
+            lang = request_dict.get('lang', None)
+            response = ResponseObject(lang if lang else token_obj.lang)
+            return token_obj.code, token_obj.userID, response
+        except Exception as e:
+            print(e)

+ 3 - 3
Service/EquipmentInfoService.py

@@ -269,9 +269,9 @@ class EquipmentInfoService:
         comb_ai_event_type = []
         for i in range(1, len(type) + 1):  # 计算所有组合,如[1, 2, 3, 4], 4取1,4取2,4取3,4取4
             for s in itertools.combinations(type, i):
-                    s_list = list(s)
-                    s_list = [str(v) for v in s_list]
-                    comb_ai_event_type.append(s_list)
+                s_list = list(s)
+                s_list = [str(v) for v in s_list]
+                comb_ai_event_type.append(s_list)
         regroup_list = []
         for val in comb_ai_event_type:  # 组合ai类型组合,如[[2,3],[1,3]] -> [23, 13]
             val = ''.join(val)

+ 0 - 10
Service/ModelService.py

@@ -213,16 +213,6 @@ class ModelService:
         file.flush()
         file.close()
 
-    @staticmethod
-    def delete_log(ip, userID, operation, UID):
-        file_path = '/'.join((BASE_DIR, 'static/delete_device.log'))
-        file = open(file_path, 'a+')
-        file.write(ip + "; username:" + userID + "; time:" + time.strftime(
-            "%Y-%m-%d %H:%M:%S", time.localtime()) + "; " + operation + "; uid:" + UID)
-        file.write('\n')
-        file.flush()
-        file.close()
-
     @staticmethod
     def add_ip_log(ip, info):
         file_path = '/'.join((BASE_DIR, 'static/get_timezone.log'))

+ 0 - 95
Service/OperatingLogs.py

@@ -1,95 +0,0 @@
-import json
-import threading
-import datetime
-import time
-
-from bson import utc
-
-from Model.models import EquipmentLogModel
-from Service.CommonService import CommonService
-from Service.MiscellService import MiscellService
-from Service.TemplateService import TemplateService
-
-
-def add_access_log(request, status_code):
-    # 增加多进程 异步
-    asy = threading.Thread(target=addLog, args=(request, status_code))
-    asy.start()
-
-
-def addLog(request, status_code):
-    request_path = request.path.strip().strip('/')
-    if 'equipment' in request.path:
-        global request_dict
-        try:
-            if request.method == 'GET':
-                request_dict = request.GET
-            elif request.method == 'POST':
-                request_dict = request.POST
-            # api_list = TemplateService.log_api()
-            print('status_code:', status_code)
-            api_list = [
-                'equipment/add',
-                'equipment/delete',
-                'equipment/flowUpdate',
-                'v3/equipment/add',
-                'v3/equipment/modify',
-            ]
-            # 接口中文化
-            jiekou = {
-                'equipment/add': 'v1添加设备',
-                'equipment/delete': 'v1删除设备',
-                'equipment/flowUpdate': '更新设备的版本信息',
-                'v3/equipment/add': 'v3添加设备信息',
-                'v3/equipment/modify': 'v3编辑设备信息'
-            }
-            if request_path in api_list:
-                user = MiscellService.get_access_name(request_dict=request_dict)
-                clientIP = CommonService.get_ip_address(request)
-                # now_time = datetime.datetime.utcnow().replace(tzinfo=utc).astimezone(utc)
-                nowtime = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())
-                beijing = datetime.timezone(datetime.timedelta(hours=8))
-                utc = datetime.timezone.utc  # 获取 UTC 的时区对象
-                beijing_time = datetime.datetime.utcnow().replace(tzinfo=utc).astimezone(beijing)  # 强制转换加上 UTC 时区。此处敲黑板,需要特别注意。
-                # content:从前端获取到的参数数据,对获取到的数据进行处理
-                content = json.dumps(request_dict)
-                d = eval(content)
-                if 'uid' not in d:
-                    d['uid'] = ''
-                if 'NickName' not in d:
-                    d['NickName'] = ''
-                if 'equipmentid' not in d:
-                    d['equipmentid'] = ''
-                if 'UID' in d:
-                    d['uid'] = d['UID']
-                if 'id' in d:
-                    d['equipmentid'] = d['id']
-                password = request_dict.get('userPwd', None)
-                if password is not None:
-                    request_dict = dict(request_dict)
-                    request_dict.pop('userPwd')
-                if user != '':
-                    user = user
-                else:
-                    print('空')
-                    user = '空'
-                # 数据拼接
-                caozuo = '用户账号为:[' + user + ']' + '在' + str(beijing_time) + '进行' + str(jiekou[request_path])
-                # + ',' + '设备uid或主键id为:' + str(d['uid']) + str(d['equipmentid'])
-                print('request_dict:', d)
-                add_data = {
-                    'user': user,
-                    'uid': d['uid'],
-                    'equipmentid': d['equipmentid'],
-                    'NickName': d['NickName'],
-                    'ip': clientIP,
-                    'time': beijing_time,
-                    'url': request.path,
-                    'operatingcontent': caozuo,
-                }
-                print('操作数据:', add_data)
-                # 设备日志添加
-                EquipmentLogModel.objects.create(**add_data)
-        except Exception as e:
-            print(repr(e))
-            pass

+ 0 - 4
Service/middleware.py

@@ -7,7 +7,6 @@ from Ansjer.config import SERVER_TYPE
 
 from Object.ResponseObject import ResponseObject
 from Service.MiscellService import MiscellService
-from Service import OperatingLogs
 from Service import CloudLogs
 import django.db
 
@@ -90,9 +89,6 @@ class StatisticsUrlMiddleware(MiddlewareMixin):
                 pass
                 # mysql
                 if SERVER_TYPE!="Ansjer.formal_settings":
-                    # print('添加日志')
-                    # CloudLogs.batch_add_access_log(request=request, status_code=response.status_code)
-                    OperatingLogs.add_access_log(request=request, status_code=response.status_code)
                     MiscellService.add_access_log(request=request, status_code=response.status_code)
                 # else:
                 #     print('不添加日志')