Browse Source

更新网关代码

locky 1 year ago
parent
commit
c2397e2708

+ 13 - 0
Ansjer/Config/gatewaySensorConfig.py

@@ -8,6 +8,19 @@
 # MQTT主题名
 SMART_SCENE_TOPIC = 'loocam/gateway_sensor/smart_scene/{}'
 GET_SCENE_TOPIC = 'loocam/gateway_sensor/get_scene/{}'
+SUB_DEVICE_TOPIC = 'loocam/gateway_sensor/sub_device/{}'
+VOICE_AUDITION_TOPIC = 'loocam/gateway_sensor/voice_audition/{}'
+
+# 智能场景事件
+SCENE_EVENT_CREATE = 1
+SCENE_EVENT_EDIT = 2
+SCENE_EVENT_DELETE = 3
+SCENE_EVENT_EDIT_STATUS = 4
+SCENE_EVENT_SOS = 5
+
+# 智能场景状态
+SCENE_STATUS_ON = 1
+SCENE_STATUS_OFF = 0
 
 # 传感器类型
 SENSOR_TYPE = {

+ 3 - 1
Ansjer/server_urls/loocam_url.py

@@ -9,7 +9,8 @@
 from django.urls import re_path
 
 from Controller.SensorGateway import GatewayFamilyRoomController, SubDeviceController, GatewayFamilyMemberController, \
-    EquipmentFamilyController, GatewayDeviceController, SmartSceneController, SmartSocketController
+    EquipmentFamilyController, GatewayDeviceController, SmartSceneController, SmartSocketController, \
+    SmartSwitchController
 
 urlpatterns = [
     re_path(r'^sensor/gateway/(?P<operation>.*)$', EquipmentFamilyController.EquipmentFamilyView.as_view()),
@@ -20,4 +21,5 @@ urlpatterns = [
     re_path(r'^gateway/device/info/(?P<operation>.*)$', GatewayDeviceController.GatewayDeviceView.as_view()),
     re_path(r'^smartscene/(?P<operation>.*)$', SmartSceneController.SmartSceneView.as_view()),
     re_path(r'^open/socket/(?P<operation>.*)$', SmartSocketController.SmartSocketView.as_view()),
+    re_path(r'^smartswitch/(?P<operation>.*)$', SmartSwitchController.SmartSwitchView.as_view()),
 ]

+ 1 - 1
Controller/SensorGateway/EquipmentFamilyController.py

@@ -1110,4 +1110,4 @@ class EquipmentFamilyView(View):
 
             return response.json(0, device_dict)
         except Exception as e:
-            return response.json(500, repr(e))
+            return response.json(500, 'error_line:{}, error_msg:{}'.format(e.__traceback__.tb_lineno, repr(e)))

+ 142 - 63
Controller/SensorGateway/GatewayDeviceController.py

@@ -7,6 +7,7 @@
 @Software: PyCharm
 """
 import datetime
+import threading
 import time
 
 import requests
@@ -14,7 +15,7 @@ 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 Ansjer.Config.gatewaySensorConfig import SMART_SCENE_TOPIC, SCENE_EVENT_DELETE, SUB_DEVICE_TOPIC
 from Ansjer.config import CONFIG_INFO, AWS_IOT_SES_ACCESS_CHINA_ID, AWS_IOT_SES_ACCESS_CHINA_SECRET, \
     AWS_IOT_SES_ACCESS_CHINA_REGION, AWS_IOT_SES_ACCESS_FOREIGN_ID, AWS_IOT_SES_ACCESS_FOREIGN_SECRET, \
     AWS_IOT_SES_ACCESS_FOREIGN_REGION_AMERICA
@@ -23,12 +24,13 @@ from Controller.SensorGateway.EquipmentFamilyController import EquipmentFamilyVi
 from Controller.SensorGateway.SmartSocketController import SmartSocketView
 from Model.models import FamilyRoomDevice, FamilyRoom, GatewaySubDevice, Device_Info, UserFamily, FamilyMember, \
     UidSetModel, iotdeviceInfoModel, SmartScene, SceneLog, SocketInfo, SocketPowerStatistics, SocketSchedule, \
-    CountryModel
+    CountryModel, SensorRecord
 from Object.AWS.AWSIoTDataPlaneUtil import AWSIoTDataPlaneService
 from Object.RedisObject import RedisObject
 from Object.ResponseObject import ResponseObject
 from Object.TokenObject import TokenObject
 from Service.CommonService import CommonService
+from Service.ModelService import ModelService
 
 
 class GatewayDeviceView(View):
@@ -49,6 +51,9 @@ class GatewayDeviceView(View):
         if operation == 'bind-serial-user':
             response = ResponseObject()
             return self.bind_serial_user(request_dict, response)
+        elif operation == 'reset':
+            response = ResponseObject()
+            return self.reset(request_dict, response)
 
         token = TokenObject(request.META.get('HTTP_AUTHORIZATION'))
         lang = request_dict.get('lang', None)
@@ -163,6 +168,7 @@ class GatewayDeviceView(View):
         @param response:
         @return:
         """
+        LOGGER.info('开始删除设备:{}'.format(request_dict))
         device_id = request_dict.get('deviceId')
         family_id = request_dict.get('familyId')
         # 1 删除网关 否则删除子设备
@@ -177,35 +183,53 @@ class GatewayDeviceView(View):
                 if device_id:
                     device_qs = Device_Info.objects.filter(id=device_id)
                     if device_qs.exists():
-                        family_device_qs = FamilyRoomDevice.objects.filter(device_id=device_id)
-                        if family_device_qs.exists():
-                            family_device_qs.delete()
-                        uid_set_qs = UidSetModel.objects.filter(uid=device_qs.first().UID)
-                        if uid_set_qs.exists():
-                            uid_set_qs.delete()
+                        serial_number = device_qs.first().serial_number
+                        FamilyRoomDevice.objects.filter(device_id=device_id).delete()
+                        UidSetModel.objects.filter(uid=device_qs.first().UID).delete()
                         socket_info_qs = SocketInfo.objects.filter(device_id=device_id)
                         if socket_info_qs.exists():
                             # 设备在不在线, 都发布重置
-                            serial_number = device_qs.first().serial_number
                             cls.reset_device(serial_number)
                             socket_info_qs.delete()
-                            socket_power_qs = SocketPowerStatistics.objects.filter(device_id=device_id)
-                            if socket_power_qs.exists():
-                                socket_power_qs.delete()
-                            socket_schedule_qs = SocketSchedule.objects.filter(device_id=device_id)
-                            if socket_schedule_qs.exists():
-                                socket_schedule_qs.delete()
-                            scene_log_qs = SceneLog.objects.filter(device_id=serial_number)
-                            if scene_log_qs.exists():
-                                scene_log_qs.delete()
+                            SocketPowerStatistics.objects.filter(device_id=device_id).delete()
+                            SocketSchedule.objects.filter(device_id=device_id).delete()
+                            SceneLog.objects.filter(device_id=serial_number).delete()
                             SmartSocketView.delete_alexa_socket(serial_number)
-
+                        # 重置设备
+                        topic_name = SUB_DEVICE_TOPIC.format(serial_number)
+                        msg = {
+                            'zigbee': 'recover',
+                        }
+                        success = CommonService.req_publish_mqtt_msg(serial_number, topic_name, msg)
+                        LOGGER.info('删除重置设备结果:{}'.format(success))
+                        try:
+                            assert success
+                        except AssertionError:
+                            return response.json(10044)
+                        time.sleep(0.3)
                         # 如果有子设备,删除子设备和关联的场景数据
                         gateway_qs = GatewaySubDevice.objects.filter(device_id=device_id)
                         if gateway_qs.exists():
                             sub_id_list = gateway_qs.values_list('id', flat=True)
+                            # 删除传感器记录
+                            SensorRecord.objects.filter(gateway_sub_device_id__in=list(sub_id_list)).delete()
                             smart_scene_qs = SmartScene.objects.filter(
                                 Q(device_id=device_id) | Q(sub_device_id__in=sub_id_list))
+
+                            # 下发删除设备消息
+                            ieee_addr_list = gateway_qs.values_list('ieee_addr', flat=True)
+                            for ieee_addr in ieee_addr_list:
+                                # 删除设备
+                                msg = {
+                                    'zigbee': 'delete',
+                                    'ieee': ieee_addr
+                                }
+                                success = CommonService.req_publish_mqtt_msg(serial_number, topic_name, msg)
+                                try:
+                                    assert success
+                                except AssertionError:
+                                    return response.json(10044)
+                                time.sleep(0.3)
                         else:
                             smart_scene_qs = SmartScene.objects.filter(device_id=device_id)
                         if smart_scene_qs.exists():
@@ -215,7 +239,8 @@ class GatewayDeviceView(View):
                             topic_name = SMART_SCENE_TOPIC.format(serial_number)
                             for smart_scene in smart_scene_info:
                                 msg = {
-                                    'smart_scene_delete': int(smart_scene['id'])
+                                    'scene_event': SCENE_EVENT_DELETE,
+                                    'scene_id': int(smart_scene['id'])
                                 }
                                 success = CommonService.req_publish_mqtt_msg(serial_number, topic_name, msg)
                                 try:
@@ -225,44 +250,48 @@ class GatewayDeviceView(View):
                                 time.sleep(0.3)
                             smart_scene_qs.delete()
                         gateway_qs.delete()  # 删除子设备
-                        scene_log_qs = SceneLog.objects.filter(device_id=device_id)
-                        if scene_log_qs.exists():
-                            scene_log_qs.delete()
+                        SceneLog.objects.filter(device_id=device_id).delete()
                         device_qs.delete()
+                        # 异步删除推送消息
+                        asy = threading.Thread(target=ModelService.del_eq_info, args=(user_id, serial_number))
+                        asy.start()
                 elif sub_ids:
-                    sub_ids = sub_ids.split(',')
-                    ids = []
-                    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)
-                            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)
+                    sub_id_list = list(map(int, sub_ids.split(',')))
+                    FamilyRoomDevice.objects.filter(sub_device__in=sub_id_list).delete()
+                    # 删除传感器记录
+                    SensorRecord.objects.filter(gateway_sub_device_id__in=sub_id_list).delete()
+                    # 查询网关序列号,确定MQTT主题
+                    sub_device_qs = GatewaySubDevice.objects.filter(id=sub_id_list[0]). \
+                        values('device__serial_number')
+                    assert sub_device_qs.exists()
+                    serial_number = sub_device_qs[0]['device__serial_number']
+
+                    # 下发删除设备消息
+                    gateway_sub_device_qs = GatewaySubDevice.objects.filter(id__in=sub_id_list)
+                    ieee_addr_list = gateway_sub_device_qs.values_list('ieee_addr', flat=True)
+                    topic_name = SUB_DEVICE_TOPIC.format(serial_number)
+                    for ieee_addr in ieee_addr_list:
+                        # 删除设备
+                        msg = {
+                            'zigbee': 'delete',
+                            'ieee': ieee_addr
+                        }
+                        success = CommonService.req_publish_mqtt_msg(serial_number, topic_name, msg)
+                        try:
+                            assert success
+                        except AssertionError:
+                            return response.json(10044)
+                        time.sleep(0.3)
+                    # 删除场景,下发MQTT通知设备
+                    smart_scene_qs = SmartScene.objects.filter(sub_device_id__in=sub_id_list)
                     if smart_scene_qs.exists():
+                        topic_name = SMART_SCENE_TOPIC.format(serial_number)
                         smart_scene_info = smart_scene_qs.values('id')
                         for smart_scene in smart_scene_info:
                             # 通知设备删除场景id
                             msg = {
-                                'smart_scene_delete': int(smart_scene['id'])
+                                'scene_event': SCENE_EVENT_DELETE,
+                                'scene_id': int(smart_scene['id'])
                             }
                             success = CommonService.req_publish_mqtt_msg(serial_number, topic_name, msg)
                             try:
@@ -271,13 +300,15 @@ class GatewayDeviceView(View):
                                 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()
+
+                    gateway_sub_device_qs.delete()
+                    SceneLog.objects.filter(sub_device_id__in=sub_id_list).delete()
+                    # 异步删除推送消息
+                    asy = threading.Thread(target=ModelService.del_eq_info, args=(user_id, serial_number))
+                    asy.start()
                 return response.json(0)
         except Exception as e:
-            print(e)
-            return response.json(177, repr(e))
+            return response.json(177, 'error_line:{}, error_msg:{}'.format(e.__traceback__.tb_lineno, repr(e)))
 
     @staticmethod
     def reset_device(serial_number):
@@ -387,10 +418,7 @@ class GatewayDeviceView(View):
                     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',
-                        'src_addr', 'status',
-                        'created_time', 'ieee_addr')
+                        'id', 'device_type', 'nickname', 'status', 'created_time', 'ieee_addr')
                     if not gateway_sub_qs.exists():
                         continue
                     room_id = item['room_id']
@@ -401,7 +429,6 @@ class GatewayDeviceView(View):
                         'gatewaySubId': gateway_sub_qs['id'],
                         'nickName': gateway_sub_qs['nickname'],
                         'deviceType': gateway_sub_qs['device_type'],
-                        'srcAddr': gateway_sub_qs['src_addr'],
                         'status': gateway_sub_qs['status'],
                         'createdTime': gateway_sub_qs['created_time'],
                         'roomName': gateway_room_name,
@@ -480,13 +507,15 @@ class GatewayDeviceView(View):
         if not all([user_id, serial_number]):
             return response.json(444)
         try:
+            now_time = int(time.time())
+            LOGGER.info('用户{}的设备{}上传序列号时间:{}'.format(user_id, serial_number, now_time))
             redis_obj = RedisObject()
             result = redis_obj.set_data(user_id, serial_number, 300)
             if not result:
                 return response.json(178)
             return response.json(0)
         except Exception as e:
-            return response.json(500, repr(e))
+            return response.json(500, 'error_line:{}, error_msg:{}'.format(e.__traceback__.tb_lineno, repr(e)))
 
     @staticmethod
     def get_serial_user(user_id, request_dict, response):
@@ -498,13 +527,63 @@ class GatewayDeviceView(View):
         @return:
         """
         try:
+            now_time = int(time.time())
             redis_obj = RedisObject()
             serial_number = redis_obj.get_data(user_id)
+            LOGGER.info('用户{}的设备{}获取序列号时间:{}'.format(user_id, serial_number, now_time))
             if not serial_number:
                 return response.json(173)
             return response.json(0, {'serialNumber': serial_number})
         except Exception as e:
-            return response.json(500, repr(e))
+            return response.json(500, 'error_line:{}, error_msg:{}'.format(e.__traceback__.tb_lineno, repr(e)))
+
+    @staticmethod
+    def reset(request_dict, response):
+        """
+        网关复位删除设备信息
+        @param request_dict: 请求参数字典
+        @request_dict serial_number: 序列号
+        @param response: 响应对象
+        @return:
+        """
+        serial_number = request_dict.get('serial_number')
+        if not serial_number:
+            return response.json(444)
+        try:
+            with transaction.atomic():
+                device_qs = Device_Info.objects.filter(serial_number=serial_number)
+                device_id_list = list(device_qs.values_list('id', flat=True))
+                user_id_list = list(device_qs.values_list('userID_id', flat=True))
+                if not device_qs.exists():
+                    return response.json(173)
+
+                FamilyRoomDevice.objects.filter(device_id__in=device_id_list).delete()
+                UidSetModel.objects.filter(uid=device_qs.first().UID).delete()
+                socket_info_qs = SocketInfo.objects.filter(device_id__in=device_id_list)
+                if socket_info_qs.exists():
+                    socket_info_qs.delete()
+                    SocketPowerStatistics.objects.filter(device_id__in=device_id_list).delete()
+                    SocketSchedule.objects.filter(device_id__in=device_id_list).delete()
+                    SmartSocketView.delete_alexa_socket(serial_number)
+
+                # 如果有子设备,删除子设备和关联的场景数据,删除传感器记录
+                gateway_qs = GatewaySubDevice.objects.filter(device_id__in=device_id_list)
+                if gateway_qs.exists():
+                    sub_id_list = gateway_qs.values_list('id', flat=True)
+                    SensorRecord.objects.filter(gateway_sub_device_id__in=list(sub_id_list)).delete()
+                    SmartScene.objects.filter(Q(device_id__in=device_id_list) | Q(sub_device_id__in=sub_id_list)).delete()
+                else:
+                    SmartScene.objects.filter(device_id__in=device_id_list).delete()
+
+                gateway_qs.delete()  # 删除子设备
+                SceneLog.objects.filter(device_id__in=device_id_list).delete()
+                device_qs.delete()
+                # 异步删除推送消息
+                asy = threading.Thread(target=ModelService.del_user_list_eq_info, args=(user_id_list, serial_number))
+                asy.start()
+            return response.json(0)
+        except Exception as e:
+            return response.json(500, 'error_line:{}, error_msg:{}'.format(e.__traceback__.tb_lineno, repr(e)))
 
     @classmethod
     def update_socket(cls, serial_number, device_name, user_id):

+ 4 - 4
Controller/SensorGateway/GatewayFamilyRoomController.py

@@ -312,7 +312,7 @@ class GatewayFamilyRoomView(View):
             device_room['sort'] = list(sort)
             return response.json(0, device_room)
         except Exception as e:
-            return response.json(500, repr(e))
+            return response.json(500, 'error_line:{}, error_msg:{}'.format(e.__traceback__.tb_lineno, repr(e)))
 
     @staticmethod
     def devices_sort(request_dict, response):
@@ -339,7 +339,7 @@ class GatewayFamilyRoomView(View):
                         FamilyRoomDevice.objects.filter(sub_device=device_id).update(sort=i)
             return response.json(0)
         except Exception as e:
-            return response.json(500, repr(e))
+            return response.json(500, 'error_line:{}, error_msg:{}'.format(e.__traceback__.tb_lineno, repr(e)))
 
     @staticmethod
     def device_category(request_dict, response):
@@ -363,7 +363,7 @@ class GatewayFamilyRoomView(View):
                     item['category_name'] = '摄像头类'
             return response.json(0, list(family_room_device_qs))
         except Exception as e:
-            return response.json(500, repr(e))
+            return response.json(500, 'error_line:{}, error_msg:{}'.format(e.__traceback__.tb_lineno, repr(e)))
 
     @staticmethod
     def category_sort(request_dict, response):
@@ -390,4 +390,4 @@ class GatewayFamilyRoomView(View):
                         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))
+            return response.json(500, 'error_line:{}, error_msg:{}'.format(e.__traceback__.tb_lineno, repr(e)))

+ 2 - 2
Controller/SensorGateway/SensorGatewayController.py

@@ -57,7 +57,7 @@ class SensorGateway(View):
             sensor_id = ''.join(random.sample(string.ascii_letters + string.digits, 6))
             return response.json(0, {'sensor_id': sensor_id})
         except Exception as e:
-            return response.json(500, repr(e))
+            return response.json(500, 'error_line:{}, error_msg:{}'.format(e.__traceback__.tb_lineno, repr(e)))
 
     @staticmethod
     def registerToAWSIoTCore(request_dict, response):
@@ -77,4 +77,4 @@ class SensorGateway(View):
         try:
             return response.json(0)
         except Exception as e:
-            return response.json(500, repr(e))
+            return response.json(500, 'error_line:{}, error_msg:{}'.format(e.__traceback__.tb_lineno, repr(e)))

+ 201 - 73
Controller/SensorGateway/SmartSceneController.py

@@ -12,7 +12,9 @@ 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 Ansjer.Config.gatewaySensorConfig import SMART_SCENE_TOPIC, SENSOR_TYPE, EVENT_TYPE, SCENE_EVENT_CREATE, \
+    SCENE_EVENT_EDIT, SCENE_EVENT_DELETE, SCENE_STATUS_ON, SCENE_STATUS_OFF, SCENE_EVENT_EDIT_STATUS, \
+    VOICE_AUDITION_TOPIC
 from Model.models import FamilyRoomDevice, GatewaySubDevice, FamilyRoom, SmartScene, EffectiveTime, Device_Info, \
     SceneLog
 from Object.ResponseObject import ResponseObject
@@ -58,6 +60,8 @@ class SmartSceneView(View):
             return self.scene_log(request_dict, response)
         elif operation == 'log-date':  # 查询智能场景日志日期
             return self.scene_log_date(request_dict, response)
+        elif operation == 'voice-audition':  # 智能场景音频试听
+            return self.voice_audition(request_dict, response)
         else:
             return response.json(414)
 
@@ -84,7 +88,7 @@ class SmartSceneView(View):
             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))
+            return response.json(500, 'error_line:{}, error_msg:{}'.format(e.__traceback__.tb_lineno, repr(e)))
 
     @classmethod
     def task_devices(cls, request_dict, response):
@@ -114,8 +118,9 @@ class SmartSceneView(View):
                 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')
+                        Q(Q(device_id=device_id) & Q(device_type=SENSOR_TYPE['door_magnet'])) |
+                        Q(Q(device_id=device_id) & Q(device_type=SENSOR_TYPE['body_sensor']))
+                    ).values('id', 'nickname', 'status', 'device_type')
                     if sub_device_qs.exists():
                         res = cls.get_sub_device_room_name(sub_device_qs, gateway_data)
                     else:
@@ -123,7 +128,7 @@ class SmartSceneView(View):
 
             return response.json(0, res)
         except Exception as e:
-            return response.json(500, repr(e))
+            return response.json(500, 'error_line:{}, error_msg:{}'.format(e.__traceback__.tb_lineno, repr(e)))
 
     @staticmethod
     def get_sub_device_room_name(sub_device_qs, gateway_data=None):
@@ -161,13 +166,15 @@ class SmartSceneView(View):
         @param device_id: 网关设备id
         @return: res
         """
-        device_info_qs = Device_Info.objects.filter(id=device_id).values('NickName', 'Type')
+        device_info_qs = Device_Info.objects.filter(id=device_id).values('NickName', 'Type', 'serial_number')
         nickname = device_info_qs[0]['NickName']
         device_type = device_info_qs[0]['Type']
+        serial_number = device_info_qs[0]['serial_number']
         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 = {
+            'serialNumber': serial_number,
             'deviceNickName': nickname,
             'deviceType': device_type,
             'roomName': room_name,
@@ -175,8 +182,8 @@ class SmartSceneView(View):
         }
         return res
 
-    @staticmethod
-    def create_smart_scene(request_dict, user_id, response):
+    @classmethod
+    def create_smart_scene(cls, request_dict, user_id, response):
         """
         创建智能场景
         @param request_dict: 请求参数
@@ -222,7 +229,8 @@ class SmartSceneView(View):
                 'updated_time': now_time,
             }
             msg = {
-                'scene_status': 1
+                'scene_event': SCENE_EVENT_CREATE,
+                'scene_status': SCENE_STATUS_ON
             }
             # 处理设置时间
             if is_all_day is not None:
@@ -238,10 +246,19 @@ class SmartSceneView(View):
                 if not device_info_qs.exists():
                     return response.json(173)
                 serial_number = device_info_qs[0]['serial_number']
+
+                # 网关数据
+                msg['sensor_type'] = 200
+                msg['sensor_status'] = 2002
+                msg['sensor_ieee_addr'] = 'FFFFFFFFFFFFFFFF'
+
             else:  # 子设备设置场景
                 if not sub_device_id:
                     return response.json(444, {'error param': 'subDeviceId'})
 
+                if cls.time_conflict(sub_device_id, conditions, is_all_day, request_dict):
+                    return response.json(182)
+
                 device_type = int(conditions_dict['sensor']['device_type'])
                 # 智能按钮不能创建触发条件相同的场景
                 if device_type == SENSOR_TYPE['smart_button']:
@@ -265,13 +282,13 @@ class SmartSceneView(View):
 
                 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')
+                                                                                         'ieee_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_ieee_addr'] = sub_device_qs[0]['ieee_addr']
                 msg['sensor_status'] = int(conditions_dict['sensor']['eventValues'][0]['event_type'])
 
             with transaction.atomic():
@@ -313,24 +330,10 @@ class SmartSceneView(View):
                     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'])
-                    }
-
-                    # 延时
-                    if 'delay_time' in task and task['delay_time'] != 0:
-                        task_temp['sensor_delay'] = task['delay_time']
+                msg['scene_id'] = smart_scene_qs.id
 
-                    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
+                # 获取设备任务数据
+                msg['task'] = cls.get_msg_task_list(tasks_list)
 
                 smart_scene_qs.device_data = json.dumps(msg)
                 smart_scene_qs.save()
@@ -346,7 +349,7 @@ class SmartSceneView(View):
 
             return response.json(0)
         except Exception as e:
-            return response.json(500, repr(e))
+            return response.json(500, 'error_line:{}, error_msg:{}'.format(e.__traceback__.tb_lineno, repr(e)))
 
     @staticmethod
     def scene_list(request_dict, user_id, response):
@@ -394,7 +397,7 @@ class SmartSceneView(View):
                 smart_scene_list.append(smart_scene_dict)
             return response.json(0, smart_scene_list)
         except Exception as e:
-            return response.json(500, repr(e))
+            return response.json(500, 'error_line:{}, error_msg:{}'.format(e.__traceback__.tb_lineno, repr(e)))
 
     @staticmethod
     def smart_button_scene_list(request_dict, user_id, response):
@@ -447,7 +450,7 @@ class SmartSceneView(View):
                 })
             return response.json(0, scene_list)
         except Exception as e:
-            return response.json(500, repr(e))
+            return response.json(500, 'error_line:{}, error_msg:{}'.format(e.__traceback__.tb_lineno, repr(e)))
 
     @staticmethod
     def update_status(request_dict, response):
@@ -466,8 +469,9 @@ class SmartSceneView(View):
             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
+            scene_status = SCENE_STATUS_ON if is_enable == 'True' else SCENE_STATUS_OFF
             msg = {
+                'scene_event': SCENE_EVENT_EDIT_STATUS,
                 'scene_id': smart_scene_id,
                 'scene_status': scene_status
             }
@@ -493,7 +497,7 @@ class SmartSceneView(View):
                     return response.json(10044)
             return response.json(0)
         except Exception as e:
-            return response.json(500, repr(e))
+            return response.json(500, 'error_line:{}, error_msg:{}'.format(e.__traceback__.tb_lineno, repr(e)))
 
     @staticmethod
     def scene_detail(request_dict, response):
@@ -537,10 +541,10 @@ class SmartSceneView(View):
             return response.json(0, res)
 
         except Exception as e:
-            return response.json(500, repr(e))
+            return response.json(500, 'error_line:{}, error_msg:{}'.format(e.__traceback__.tb_lineno, repr(e)))
 
-    @staticmethod
-    def edit_smart_scene(request_dict, user_id, response):
+    @classmethod
+    def edit_smart_scene(cls, request_dict, user_id, response):
         """
         编辑智能场景
         @param request_dict: 请求参数
@@ -585,13 +589,17 @@ class SmartSceneView(View):
 
             scene_status = 1 if smart_scene_qs[0].is_enable else 0
             msg = {
-                'smart_scene_id': smart_scene_id,
+                'scene_id': smart_scene_id,
+                'scene_event': SCENE_EVENT_EDIT,
                 'scene_status': scene_status
             }
             if conditions_dict['type'] == 2:  # 条件为选择子设备
                 if not sub_device_id:
                     return response.json(444, {'error param': 'subDeviceId'})
 
+                if cls.time_conflict(sub_device_id, conditions, is_all_day, request_dict, smart_scene_id):
+                    return response.json(182)
+
                 device_type = int(conditions_dict['sensor']['device_type'])
                 # 智能按钮不能创建触发条件相同的场景
                 if device_type == SENSOR_TYPE['smart_button']:
@@ -615,13 +623,13 @@ class SmartSceneView(View):
                     msg['sensor_data'] = float(value)
 
                 device_id = ''
-                sub_device_qs = GatewaySubDevice.objects.filter(id=sub_device_id).values('src_addr',
+                sub_device_qs = GatewaySubDevice.objects.filter(id=sub_device_id).values('ieee_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_ieee_addr'] = sub_device_qs[0]['ieee_addr']
                 msg['sensor_status'] = int(conditions_dict['sensor']['eventValues'][0]['event_type'])
             else:
                 if not device_id:
@@ -631,24 +639,13 @@ class SmartSceneView(View):
                 if not device_qs.exists():
                     return response.json(173)
                 serial_number = device_qs[0]['serial_number']
+                # 网关数据
+                msg['sensor_type'] = 200
+                msg['sensor_status'] = 2002
+                msg['sensor_ieee_addr'] = 'FFFFFFFFFFFFFFFF'
 
-            task_list = []
-            for task in tasks_list:
-                task_temp = {
-                    'sensor_type': int(task['device_type']),
-                    'sensor_action': int(task['event_type'])
-                }
-
-                # 延时
-                if 'delay_time' in task and task['delay_time'] != 0:
-                    task_temp['sensor_delay'] = task['delay_time']
-
-                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
+            # 获取设备任务数据
+            msg['task'] = cls.get_msg_task_list(tasks_list)
 
             with transaction.atomic():
                 smart_scene_qs.update(scene_name=scene_name, conditions=conditions, tasks=tasks,
@@ -705,7 +702,7 @@ class SmartSceneView(View):
             return response.json(0, res)
 
         except Exception as e:
-            return response.json(500, repr(e))
+            return response.json(500, 'error_line:{}, error_msg:{}'.format(e.__traceback__.tb_lineno, repr(e)))
 
     @staticmethod
     def delete_smart_scene(request_dict, response):
@@ -737,7 +734,8 @@ class SmartSceneView(View):
                 for smart_scene_id in smart_scene_id_list:
                     # 通知设备删除场景id
                     msg = {
-                        'smart_scene_delete': int(smart_scene_id)
+                        'scene_event': SCENE_EVENT_DELETE,
+                        'scene_id': int(smart_scene_id)
                     }
                     success = CommonService.req_publish_mqtt_msg(serial_number, topic_name, msg)
                     try:
@@ -747,7 +745,7 @@ class SmartSceneView(View):
                     time.sleep(0.3)
             return response.json(0)
         except Exception as e:
-            return response.json(500, repr(e))
+            return response.json(500, 'error_line:{}, error_msg:{}'.format(e.__traceback__.tb_lineno, repr(e)))
 
     @staticmethod
     def scene_log(request_dict, response):
@@ -783,17 +781,19 @@ class SmartSceneView(View):
                     device_list.append(device['device'])
                 if device['sub_device']:
                     sub_device_list.append(device['sub_device'])
-        elif sub_device_id:
-            family_room_device_qs = FamilyRoomDevice.objects.filter(family_id=family_id, sub_device=sub_device_id)
+        elif sub_device_id:  # 查询子设备
+            family_room_device_qs = FamilyRoomDevice.objects.filter(family_id=family_id,
+                                                                    sub_device=sub_device_id).values('device_id')
+            for device in family_room_device_qs:
+                device_list.append(device['device_id'])
             sub_device_list.append(sub_device_id)
-        else:
-            family_room_device_qs = FamilyRoomDevice.objects.filter(family_id=family_id, device=device_id).values(
+        else:  # 查询网关
+            family_room_device_qs = FamilyRoomDevice.objects.filter(Q(family_id=family_id) & Q(device=device_id) &
+                                                                    ~Q(sub_device=0)).values(
                 'sub_device')
             device_list.append(device_id)
             for device in family_room_device_qs:
                 sub_device_list.append(device['sub_device'])
-        if not family_room_device_qs.exists():
-            return response.json(173)
         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))
@@ -828,11 +828,13 @@ class SmartSceneView(View):
                 else:
                     device_qs = Device_Info.objects.filter(id=item['device_id']).values('Type')
                     item['device_type'] = device_qs[0]['Type'] if device_qs.exists() else ''
-                item['tasks'] = eval(item['tasks'])
-            return response.json(0, list(scene_log_qs))
+                if item['tasks'] != '':
+                    item['tasks'] = eval(item['tasks'])
+            scene_log_list = list(scene_log_qs)
+            return response.json(0, scene_log_list)
         except Exception as e:
-            print(repr(e))
-            return response.json(500, repr(e))
+            print('error_line:{}, error_msg:{}'.format(e.__traceback__.tb_lineno, repr(e)))
+            return response.json(500, 'error_line:{}, error_msg:{}'.format(e.__traceback__.tb_lineno, repr(e)))
 
     @staticmethod
     def scene_log_date(request_dict, response):
@@ -886,7 +888,7 @@ class SmartSceneView(View):
                 })
             return response.json(0, log_date_list)
         except Exception as e:
-            return response.json(500, repr(e))
+            return response.json(500, 'error_line:{}, error_msg:{}'.format(e.__traceback__.tb_lineno, repr(e)))
 
     @staticmethod
     def get_scene_data(request_dict, response):
@@ -931,14 +933,14 @@ class SmartSceneView(View):
             # 下发智能按钮数据
             smart_button_qs = GatewaySubDevice.objects.filter(device_id=device_id,
                                                               device_type=SENSOR_TYPE['smart_button']).values(
-                'src_addr', 'is_tampered')
+                'ieee_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),
+                        'sensor_ieee_addr': smart_button['ieee_addr'],
                         'sos_select': smart_button['is_tampered']
                     }
                     success = CommonService.req_publish_mqtt_msg(serial_number, topic_name, msg)
@@ -950,7 +952,133 @@ class SmartSceneView(View):
 
             return response.json(0)
         except Exception as e:
-            return response.json(500, repr(e))
+            return response.json(500, 'error_line:{}, error_msg:{}'.format(e.__traceback__.tb_lineno, repr(e)))
+
+    @staticmethod
+    def voice_audition(request_dict, response):
+        """
+        智能场景音频试听
+        @param request_dict: 请求参数
+        @request_dict serial_number: 序列号
+        @request_dict voiceId: 音频id
+        @param response: 响应对象
+        @return: response
+        """
+        serial_number = request_dict.get('serial_number', None)
+        voice_id = request_dict.get('voiceId', None)
+        if not all([serial_number, voice_id]):
+            return response.json(444)
+        try:
+            topic_name = VOICE_AUDITION_TOPIC.format(serial_number)
+            msg = {'voice_id': int(voice_id)}
+            success = CommonService.req_publish_mqtt_msg(serial_number, topic_name, msg)
+            try:
+                assert success
+            except AssertionError:
+                return response.json(10044)
+            return response.json(0)
+        except Exception as e:
+            return response.json(500, 'error_line:{}, error_msg:{}'.format(e.__traceback__.tb_lineno, repr(e)))
+
+    @staticmethod
+    def get_msg_task_list(tasks_list):
+        """
+        获取设备任务数据
+        @param tasks_list: app任务列表
+        @return: task_list
+        """
+        task_list = []
+        for task in tasks_list:
+            sensor_type = int(task['device_type'])
+            task_temp = {
+                'sensor_type': sensor_type,
+                'sensor_delay': 0
+            }
+
+            # 延时
+            if 'delay_time' in task and task['delay_time'] != 0:
+                task_temp['sensor_delay'] = task['delay_time']
+
+            # 不为-1时需要其他数据
+            if sensor_type != -1:
+                task_temp['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('ieee_addr').first()
+                    task_temp['sensor_ieee_addr'] = sub_device_qs['ieee_addr']
+                # 网关添加报警类型数据
+                else:
+                    task_temp['voice_type'] = task.get('voice_type')
+                    task_temp['voice_id'] = task.get('voice_id')
+                    task_temp['count'] = task.get('count')
+                    task_temp['delay_time'] = task.get('delay_time')
+                    task_temp['duration'] = task.get('duration')
+                    task_temp['value_type'] = task.get('value_type')
+            task_list.append(task_temp)
+        return task_list
+
+    @staticmethod
+    def time_conflict(sub_device_id, conditions, is_all_day, request_dict, smart_scene_id=None):
+        """
+        判断传感器是否创建过条件相同且生效时间冲突的场景
+        @param sub_device_id: 传感器设备id
+        @param conditions: 场景条件
+        @param is_all_day: 全天标识
+        @param request_dict:
+        @param smart_scene_id: 场景id,编辑场景时传
+        @return: bool, True: 冲突, False: 不冲突
+        """
+        # 不设置时间不会冲突
+        if is_all_day is None:
+            return False
+
+        # 查询设置过时间的数据
+        if smart_scene_id is None:  # 创建场景
+            smart_scene_qs = SmartScene.objects.filter(
+                ~Q(is_all_day=0),
+                sub_device_id=sub_device_id,
+                conditions=conditions).values('effective_time_id')
+        else:   # 编辑场景,过滤本身场景数据
+            smart_scene_qs = SmartScene.objects.filter(
+                ~Q(id=smart_scene_id),
+                ~Q(is_all_day=0),
+                sub_device_id=sub_device_id,
+                conditions=conditions).values('effective_time_id')
+
+        if not smart_scene_qs.exists():
+            return False
+
+        # 再设置全天必冲突
+        if is_all_day == 1:
+            return True
+        # 非全天
+        elif is_all_day == 2:
+            start_time = int(request_dict.get('startTime'))
+            end_time = int(request_dict.get('endTime'))
+            repeat = int(request_dict.get('repeat'))
+            for smart_scene in smart_scene_qs:
+                effective_time_id = smart_scene['effective_time_id']
+                effective_time_qs = EffectiveTime.objects.filter(id=effective_time_id).\
+                    values('start_time', 'end_time', 'repeat')
+                if effective_time_qs.exists():
+                    old_start_time = effective_time_qs[0]['start_time']
+                    old_end_time = effective_time_qs[0]['end_time']
+                    old_repeat = effective_time_qs[0]['repeat']
+                    # 每天重复
+                    if repeat == 127:
+                        # 判断时间是否在已设置过的时间范围之内
+                        if old_start_time <= start_time <= old_end_time or \
+                                old_start_time <= end_time <= old_end_time:
+                            return True
+                    else:
+                        # 有相同的重复天
+                        if repeat & old_repeat != 0:
+                            # 判断时间是否在已设置过的时间范围之内
+                            if old_start_time <= start_time <= old_end_time or \
+                                    old_start_time <= end_time <= old_end_time:
+                                return True
+            return False
 
 #
 #                   ___====-_  _-====___

+ 8 - 8
Controller/SensorGateway/SmartSocketController.py

@@ -443,8 +443,8 @@ class SmartSocketView(View):
         # 确定是否会传值
         if not all([serial_number]):
             return response.json(444, {'error param': 'serialNumber'})
-        all_socket_power_qs = SocketPowerStatistics.objects.\
-            filter(serial_number=serial_number).values('electricity', 'accumulated_time', 'power', 'created_time')\
+        all_socket_power_qs = SocketPowerStatistics.objects. \
+            filter(serial_number=serial_number).values('electricity', 'accumulated_time', 'power', 'created_time') \
             .order_by('-created_time')
         if not all_socket_power_qs.exists():
             return response.json(0, {})
@@ -504,7 +504,7 @@ class SmartSocketView(View):
                 data['electricityYesterday'] = 0
             return response.json(0, data)
         except Exception as e:
-            return response.json(500, repr(e))
+            return response.json(500, 'error_line:{}, error_msg:{}'.format(e.__traceback__.tb_lineno, repr(e)))
 
     @staticmethod
     def get_socket_schedule(request_dict, response):
@@ -554,7 +554,7 @@ class SmartSocketView(View):
                 })
             return response.json(0, schedule_list)
         except Exception as e:
-            return response.json(500, repr(e))
+            return response.json(500, 'error_line:{}, error_msg:{}'.format(e.__traceback__.tb_lineno, repr(e)))
 
     @staticmethod
     def get_log(request_dict, response):
@@ -785,7 +785,7 @@ class SmartSocketView(View):
             data['week_or_month_or_year'] = new_list
             return response.json(0, data)
         except Exception as e:
-            return response.json(500, repr(e))
+            return response.json(500, 'error_line:{}, error_msg:{}'.format(e.__traceback__.tb_lineno, repr(e)))
 
     @classmethod
     def get_subscript(cls, unit, time_stamp):
@@ -840,7 +840,7 @@ class SmartSocketView(View):
                 })
             return response.json(0, schedule_date_list)
         except Exception as e:
-            return response.json(500, repr(e))
+            return response.json(500, 'error_line:{}, error_msg:{}'.format(e.__traceback__.tb_lineno, repr(e)))
 
     @classmethod
     def alexa_socket_switch(cls, request_dict, response):
@@ -866,7 +866,7 @@ class SmartSocketView(View):
             return response.json(0)
         except Exception as e:
             print(e)
-            return response.json(500, repr(e))
+            return response.json(500, 'error_line:{}, error_msg:{}'.format(e.__traceback__.tb_lineno, repr(e)))
 
     @classmethod
     def get_socket_state(cls, request_dict, response):
@@ -892,7 +892,7 @@ class SmartSocketView(View):
             return response.json(173)
         except Exception as e:
             print(e)
-            return response.json(500, repr(e))
+            return response.json(500, 'error_line:{}, error_msg:{}'.format(e.__traceback__.tb_lineno, repr(e)))
 
     @classmethod
     def delete_alexa_socket(cls, serial_number):

+ 352 - 0
Controller/SensorGateway/SmartSwitchController.py

@@ -0,0 +1,352 @@
+# -*- coding: utf-8 -*-
+"""
+# @Author : cheng
+# @Time : 2023/7/10 11:20
+# @File: SmartSwitchController.py
+"""
+
+from django.views import View
+
+from Model.models import SwitchInfo, SwitchDimmingSettings, SwitchChronopher
+from Service.CommonService import CommonService
+
+
+class SmartSwitchView(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):
+        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 == 'get-switch-info': # 设备获取智能开关数据
+            return self.get_switch_info(request_dict, response)
+        elif operation == 'get-switch-setting': # 获取智能开关调光设置
+            return self.get_switch_setting(request_dict, response)
+        elif operation == 'get-chronopher-setting': # 获取定时计划
+            return self.get_chronopher_setting(request_dict, response)
+        elif operation == 'add-or-edit-chronopher': # 添加/编辑定时计划
+            return self.add_or_edit_chronopher(request_dict, response)
+        elif operation == 'delete-chronopher': # 删除定时计划
+            return self.delete_chronopher(request_dict, response)
+        else:
+            return response.json(414)
+
+    @staticmethod
+    def get_switch_info(request_dict, response):
+        """
+        获取智能开关设备信息
+        @param request_dict: 请求参数
+        @request_dict deviceId: 设备id
+        @param response: 响应对象
+        @return: response
+        """
+        device_id = request_dict.get('deviceId', None)
+        if not device_id:
+            return response.json(444)
+        try:
+            switch_info_qs = SwitchInfo.objects.filter(device_id=device_id).values()
+            if not switch_info_qs.exists():
+                return response.json(173)
+            res = {
+                'model': switch_info_qs[0]['model'],
+                'hardwareVersion': switch_info_qs[0]['hardware_version'],
+                'firmwareVersion': switch_info_qs[0]['firmware_version'],
+                'mac': switch_info_qs[0]['mac'],
+            }
+            return response.json(0, res)
+        except Exception as e:
+            print(e)
+            return response.json(500, 'error_line:{}, error_msg:{}'.format(e.__traceback__.tb_lineno, repr(e)))
+
+    @staticmethod
+    def get_switch_setting(request_dict, response, user_id):
+        """
+        获取智能开关设备设置信息
+        @param request_dict: 请求参数
+        @param user_id: 用戶user_id
+        @request_dict deviceId: 设备id
+        @param response: 响应对象
+        @return: response
+        """
+        device_id = request_dict.get('deviceId', None)
+        if not device_id:
+            return response.json(444)
+        try:
+            switch_setting_info_qs = SwitchDimmingSettings.objects.filter(device_id=device_id).values()
+            if not switch_setting_info_qs.exists():
+                return response.json(173)
+            res = {
+                'clickTurnOnSpeed': switch_setting_info_qs[0]['click_turn_on_speed'],
+                'clickTurnOffSpeed': switch_setting_info_qs[0]['click_turn_off_speed'],
+                'doubleClick': switch_setting_info_qs[0]['double_click'],
+                'press': switch_setting_info_qs[0]['press'],
+                'doublePressClickTurnOnSpeed': switch_setting_info_qs[0]['double_press_click_turn_on_speed'],
+                'doublePressClickTurnOffSpeed': switch_setting_info_qs[0]['double_press_click_turn_off_speed'],
+                'led': switch_setting_info_qs[0]['led'],
+                'dimmingCorrection': switch_setting_info_qs[0]['dimming_correction'],
+            }
+            return response.json(0, res)
+        except Exception as e:
+            print(e)
+            return response.json(500, 'error_line:{}, error_msg:{}'.format(e.__traceback__.tb_lineno, repr(e)))
+
+    @staticmethod
+    def edit_switch_setting(request_dict, response):
+        """
+        修改智能开关设备设置
+        @param request_dict: 请求参数
+        @request_dict deviceId: 设备id
+        @request_dict deviceNickname: 设备名称
+        @request_dict location: 位置
+        @request_dict led: LED指示灯
+        @request_dict dimmingCorrection: 调光校正
+        @param response: 响应对象
+        @return: response
+        """
+        device_id = request_dict.get('deviceId', None)
+        device_nick_name = request_dict.get('deviceNickname', None)
+        location = request_dict.get('location', None)
+        led = request_dict.get('led', None)
+        dimming_correction = request_dict.get('dimmingCorrection', None)
+
+        if not device_id:
+            return response.json(444)
+        try:
+            switch_setting_data = {
+                'device_id': device_id,
+                'led': led,
+                'dimming_correction': dimming_correction,
+            }
+            SwitchDimmingSettings.objects.filter(device_id=device_id).update(**switch_setting_data)
+            return response.json(0)
+        except Exception as e:
+            print(e)
+            return response.json(500, 'error_line:{}, error_msg:{}'.format(e.__traceback__.tb_lineno, repr(e)))
+
+    @staticmethod
+    def edit_dimming_setting(request_dict, response):
+        """
+        修改智能开关调光设置
+        @param request_dict: 请求参数
+        @request_dict deviceId: 设备id
+        @request_dict clickTurnOnSpeed: 单击开启速度
+        @request_dict clickTurnOffSpeed: 单击关闭速度
+        @request_dict doubleClick: 双击
+        @request_dict press: 长按
+        @request_dict doublePressClickTurnOnSpeed: 双击/长按开启速度
+        @request_dict doublePressClickTurnOffSpeed: 双击/长按单击关闭速度
+        @param response: 响应对象
+        @return: response
+        """
+        device_id = request_dict.get('deviceId', None)
+        click_turn_on_speed = request_dict.get('clickTurnOnSpeed', None)
+        click_turn_off_speed = request_dict.get('clickTurnOffSpeed', None)
+        double_click = request_dict.get('doubleClick', None)
+        press = request_dict.get('press', None)
+        double_press_click_turn_on_speed = request_dict.get('doublePressClickTurnOnSpeed', None)
+        double_press_click_turn_off_speed = request_dict.get('doublePressClickTurnOffSpeed', None)
+
+        if not device_id:
+            return response.json(444)
+        try:
+            dimming_setting_data = {
+                'device_id': device_id,
+                'click_turn_on_speed': click_turn_on_speed,
+                'click_turn_off_speed': click_turn_off_speed,
+                'double_click': double_click,
+                'press': press,
+                'double_press_click_turn_on_speed': double_press_click_turn_on_speed,
+                'double_press_click_turn_off_speed': double_press_click_turn_off_speed
+            }
+            SwitchDimmingSettings.objects.filter(device_id=device_id).update(**dimming_setting_data)
+            return response.json(0)
+        except Exception as e:
+            print(e)
+            return response.json(500, 'error_line:{}, error_msg:{}'.format(e.__traceback__.tb_lineno, repr(e)))
+
+    @staticmethod
+    def get_location_list(request_dict, response):
+        """
+        获取房间列表
+        @param request_dict: 请求参数
+        @request_dict deviceId: 设备id
+        @param response: 响应对象
+        @return: response
+        """
+        device_id = request_dict.get('deviceId', None)
+        if not device_id:
+            return response.json(444)
+        try:
+            room_list_qs = SwitchDimmingSettings.objects.filter(device_id=device_id).values('location', 'location_list')
+            res = {
+                'location': room_list_qs[0]['location'],
+                'locationList': room_list_qs[0]['location_list']
+            }
+            return response.json(0, res)
+        except Exception as e:
+            print(e)
+            return response.json(500, 'error_line:{}, error_msg:{}'.format(e.__traceback__.tb_lineno, repr(e)))
+
+    @staticmethod
+    def add_location(request_dict, response):
+        """
+        添加房间
+        @param request_dict: 请求参数
+        @request_dict deviceId: 设备id
+        @param response: 响应对象
+        @return: response
+        """
+        room_name = request_dict.get('roomName', None)
+        if not room_name:
+            return response.json(444)
+        try:
+            return response.json(0)
+        except Exception as e:
+            print(e)
+            return response.json(500, 'error_line:{}, error_msg:{}'.format(e.__traceback__.tb_lineno, repr(e)))
+
+    @staticmethod
+    def delete_location(request_dict, response):
+        """
+        删除房间
+        @param request_dict: 请求参数
+        @request_dict deviceId: 设备id
+        @param response: 响应对象
+        @return: response
+        """
+        room_name = request_dict.get('roomName', None)
+        if not room_name:
+            return response.json(444)
+        try:
+            return response.json(0)
+        except Exception as e:
+            print(e)
+            return response.json(500, 'error_line:{}, error_msg:{}'.format(e.__traceback__.tb_lineno, repr(e)))
+
+    @staticmethod
+    def get_chronopher_setting(request_dict, response):
+        """
+        获取定时计划设置
+        @param request_dict: 请求参数
+        @request_dict deviceId: 设备id
+        @param response: 响应对象
+        @return: response
+        """
+        device_id = request_dict.get('deviceId', None)
+        if not device_id:
+            return response.json(444)
+        try:
+            switch_chronopher_qs = SwitchChronopher.objects.filter(device_id=device_id).values()
+            if not switch_chronopher_qs.exists():
+                return response.json(173)
+            switch_chronopher_list = []
+            for item in switch_chronopher_qs:
+                switch_chronopher_list.append({
+                    'chronopherId': item['id'],
+                    'timeTypeRadio': item['time_type_radio'],
+                    'timePoint': item['time_point'],
+                    'timeQuantumStartTime': item['time_quantum_start_time'],
+                    'timeQuantumEndTime': item['time_quantum_end_time'],
+                    'timePointDeviceWillDoing': item['time_point_device_will_doing'],
+                    'timeQuantumDeviceWillDoing': item['time_quantum_device_will_doing'],
+                    'slowOpenOrCloseSpeed': item['slow_open_or_close_speed'],
+                    'repeat': item['repeat'],
+                })
+            return response.json(0, {'list': switch_chronopher_list})
+        except Exception as e:
+            print(e)
+            return response.json(500, 'error_line:{}, error_msg:{}'.format(e.__traceback__.tb_lineno, repr(e)))
+
+    @staticmethod
+    def add_or_edit_chronopher(request_dict, response):
+        """
+        添加/编辑定时计划
+        @param request_dict: 请求参数
+        @request_dict deviceId: 设备id
+        @request_dict chronopherId: 定时计划id
+        @request_dict timeTypeRadio: 切换时间点/时间段
+        @request_dict timePoint: 时间点
+        @request_dict timeQuantumStartTime: 时间段开始时间
+        @request_dict timeQuantumEndTime: 时间段结束时间
+        @request_dict timePointDeviceWillDoing: 设备将会
+        @request_dict timeQuantumDeviceWillDoing: 设备将会
+        @request_dict slowOpenOrCloseSpeed: 缓慢开/关速度
+        @request_dict repeat: 重复周期
+        @param response: 响应对象
+        @return: response
+        """
+        is_edit = request_dict.get('isEdit', None)
+        device_id = request_dict.get('deviceId', None)
+        chronopher_id = request_dict.get('chronopherId', None)
+        time_type_radio = int(request_dict.get('timeTypeRadio', 0))
+        time_point = request_dict.get('timePoint', None)
+        time_quantum_start_time = request_dict.get('timeQuantumStartTime', None)
+        time_quantum_end_time = request_dict.get('timeQuantumEndTime', None)
+        time_point_device_will_doing = request_dict.get('timePointDeviceWillDoing', None)
+        time_quantum_device_will_doing = request_dict.get('timeQuantumDeviceWillDoing', None)
+        slow_open_or_close_speed = request_dict.get('slowOpenOrCloseSpeed', None)
+        repeat = request_dict.get('repeat', None)
+
+        if not all([device_id, time_type_radio, repeat]):
+            return response.json(444)
+        if time_type_radio == 1:
+            if not all([time_point, slow_open_or_close_speed]):
+                return response.json(444)
+            chronopher_data = {
+                'device_id': device_id,
+                'time_type_radio': time_type_radio,
+                'time_point': time_point,
+                'time_point_device_will_doing': time_point_device_will_doing,
+                'slow_open_or_close_speed': slow_open_or_close_speed
+            }
+        else:
+            if not all([time_quantum_start_time, time_quantum_end_time]):
+                return response.json(444)
+            chronopher_data = {
+                'device_id': device_id,
+                'time_type_radio': time_type_radio,
+                'time_quantum_start_time': time_quantum_start_time,
+                'time_quantum_end_time': time_quantum_end_time,
+                'time_quantum_device_will_doing': time_quantum_device_will_doing,
+            }
+        try:
+            if is_edit:
+                if not chronopher_id:
+                    return response.json(444)
+                SwitchChronopher.objects.filter(device_id=device_id, id=chronopher_id).update(**chronopher_data)
+            else:
+                SwitchChronopher.objects.create(**chronopher_data)
+            return response.json(0)
+        except Exception as e:
+            print(e)
+            return response.json(500, 'error_line:{}, error_msg:{}'.format(e.__traceback__.tb_lineno, repr(e)))
+
+    @staticmethod
+    def delete_chronopher(request_dict, response):
+        """
+        删除定时计划
+        @param request_dict: 请求参数
+        @request_dict deviceId: 设备id
+        @request_dict chronopherId: 定时计划id
+        @param response: 响应对象
+        @return: response
+        """
+        device_id = request_dict.get('deviceId', None)
+        chronopher_id = request_dict.get('chronopherId', None)
+
+        if not chronopher_id:
+            return response.json(444, {'error param': 'deviceId or chronopherId'})
+        try:
+            SwitchChronopher.objects.filter(device_id=device_id, id=chronopher_id).delete()
+            return response.json(0)
+        except Exception as e:
+            print(e)
+            return response.json(500, 'error_line:{}, error_msg:{}'.format(e.__traceback__.tb_lineno, repr(e)))

+ 87 - 71
Controller/SensorGateway/SubDeviceController.py

@@ -11,9 +11,10 @@ from django.db import transaction
 from django.db.models import Count, Q
 from django.views import View
 
-from Ansjer.Config.gatewaySensorConfig import SMART_SCENE_TOPIC, SENSOR_TYPE, EVENT_TYPE
+from Ansjer.Config.gatewaySensorConfig import SMART_SCENE_TOPIC, SENSOR_TYPE, EVENT_TYPE, SCENE_EVENT_SOS
 from Model.models import Device_Info, GatewaySubDevice, FamilyRoomDevice, SensorRecord, SmartScene, SceneLog, FamilyRoom
 from Service.CommonService import CommonService
+from Object.ResponseObject import ResponseObject
 
 
 class GatewaySubDeviceView(View):
@@ -28,13 +29,25 @@ class GatewaySubDeviceView(View):
         return self.validation(request.POST, request, operation)
 
     def validation(self, request_dict, request, operation):
+
+        if operation == 'update-online-status':  # 更新子设备在线状态
+            response = ResponseObject()
+            return self.update_online_status(request_dict, response)
+
         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)
+
+        if operation == 'home':  # 查询传感器主页信息
+            return self.sensor_home_info(request_dict, response)
+        elif operation == 'device-list':  # 获取设备信息
+            return self.get_device_list(request_dict, response)
+        elif operation == 'list':  # 获取子设备信息
+            return self.get_sensor_list(request_dict, response)
         elif operation == 'detail':  # 查询子设备信息
             return self.query_sub_device(request_dict, response)
+        elif operation == 'add':  # 添加子设备
+            return self.add_sub_device(request_dict, user_id, response)
         elif operation == 'update':  # 更新子设备信息
             return self.sensor_update(request_dict, response)
         elif operation == 'delete':  # 删除子设备
@@ -45,14 +58,8 @@ class GatewaySubDeviceView(View):
             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)
-        elif operation == 'device-list':  # 获取设备信息
-            return self.get_device_list(request_dict, response)
         else:
             return response.json(414)
 
@@ -65,7 +72,6 @@ class GatewaySubDeviceView(View):
         @request_dict deviceType: 设备类型
         @request_dict nickName: 设备名
         @request_dict ieeeAddr: 长地址
-        @request_dict srcAddr: 短地址
         @request_dict mac: mac地址
         @request_dict deviceModel: 设备型号
         @request_dict manufacturer: 制造商
@@ -82,7 +88,6 @@ class GatewaySubDeviceView(View):
         device_type = int(request_dict.get('deviceType', None))
         nickname = request_dict.get('nickName', None)
         ieee_addr = request_dict.get('ieeeAddr', None)
-        src_addr = request_dict.get('srcAddr', None)
         mac = request_dict.get('mac', '')
         device_model = request_dict.get('deviceModel', '')
         manufacturer = request_dict.get('manufacturer', '')
@@ -93,10 +98,10 @@ class GatewaySubDeviceView(View):
         family_id = request_dict.get('familyId', None)
         room_id = request_dict.get('roomId', 0)
 
-        if not all([serial_number, device_type, nickname, src_addr, family_id]):
+        if not all([serial_number, device_type, nickname, 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')
@@ -106,7 +111,6 @@ 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)
             if device_type == SENSOR_TYPE['smart_button']:
                 sub_device_qs = GatewaySubDevice.objects.filter(device_id=device_id, device_type=device_type)
@@ -115,15 +119,13 @@ class GatewaySubDeviceView(View):
 
             with transaction.atomic():
                 sub_device = GatewaySubDevice.objects.create(device_id=device_id, device_type=device_type,
-                                                             nickname=nickname, ieee_addr=ieee_addr, src_addr=src_addr,
-                                                             status=1, mac=mac, device_model=device_model,
+                                                             nickname=nickname, ieee_addr=ieee_addr,
+                                                             mac=mac, device_model=device_model,
                                                              manufacturer=manufacturer, sensor_serial=sensor_serial,
-                                                             firmware_version=firmware_version, is_tampered=is_tampered,
+                                                             firmware_version=firmware_version,
                                                              hardware_version=hardware_version,
                                                              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():
@@ -138,7 +140,7 @@ class GatewaySubDeviceView(View):
 
             return response.json(0)
         except Exception as e:
-            return response.json(500, repr(e))
+            return response.json(500, 'error_line:{}, error_msg:{}'.format(e.__traceback__.tb_lineno, repr(e)))
 
     @staticmethod
     def query_sub_device(request_dict, response):
@@ -171,7 +173,7 @@ class GatewaySubDeviceView(View):
                 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))
+            return response.json(500, 'error_line:{}, error_msg:{}'.format(e.__traceback__.tb_lineno, repr(e)))
 
     @classmethod
     def sensor_update(cls, request_dict, response):
@@ -200,7 +202,7 @@ class GatewaySubDeviceView(View):
             return response.json(0)
         except Exception as e:
             print(e.args)
-            return response.json(500, repr(e))
+            return response.json(500, 'error_line:{}, error_msg:{}'.format(e.__traceback__.tb_lineno, repr(e)))
 
     @staticmethod
     def delete_sub_device(request_dict, response):
@@ -226,7 +228,7 @@ class GatewaySubDeviceView(View):
                     scene_log_qs.delete()
             return response.json(0)
         except Exception as e:
-            return response.json(500, repr(e))
+            return response.json(500, 'error_line:{}, error_msg:{}'.format(e.__traceback__.tb_lineno, repr(e)))
 
     @classmethod
     def records_tem_hum(cls, request_dict, response):
@@ -265,7 +267,7 @@ class GatewaySubDeviceView(View):
             }
             return response.json(0, res)
         except Exception as e:
-            return response.json(500, repr(e))
+            return response.json(500, 'error_line:{}, error_msg:{}'.format(e.__traceback__.tb_lineno, repr(e)))
 
     @staticmethod
     def get_record_dict(cycle, now_time, sub_device_id, event_type):
@@ -379,7 +381,7 @@ class GatewaySubDeviceView(View):
                 return response.json(0, [])
             return response.json(0, list(sensor_record_qs))
         except Exception as e:
-            return response.json(500, repr(e))
+            return response.json(500, 'error_line:{}, error_msg:{}'.format(e.__traceback__.tb_lineno, repr(e)))
 
     @staticmethod
     def records_date(request_dict, response):
@@ -411,7 +413,7 @@ class GatewaySubDeviceView(View):
                 })
             return response.json(0, record_date_list)
         except Exception as e:
-            return response.json(500, repr(e))
+            return response.json(500, 'error_line:{}, error_msg:{}'.format(e.__traceback__.tb_lineno, repr(e)))
 
     @staticmethod
     def sensor_home_info(request_dict, response):
@@ -457,7 +459,7 @@ class GatewaySubDeviceView(View):
 
             return response.json(0, res)
         except Exception as e:
-            return response.json(500, repr(e))
+            return response.json(500, 'error_line:{}, error_msg:{}'.format(e.__traceback__.tb_lineno, repr(e)))
 
     @staticmethod
     def update_emergency_status(request_dict, response):
@@ -483,52 +485,28 @@ class GatewaySubDeviceView(View):
                 # 更新智能按钮紧急开关状态
                 sub_device_qs.update(is_tampered=emergency_status)
                 # 获取序列号
-                sub_device_qs = sub_device_qs.values('device_id', 'src_addr', 'device__serial_number')
+                sub_device_qs = sub_device_qs.values('device_id', 'ieee_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
+                    'scene_event': SCENE_EVENT_SOS,
+                    'ieee_addr': sub_device_qs[0]['ieee_addr'],
+                    'sos': emergency_status
                 }
                 success = CommonService.req_publish_mqtt_msg(serial_number, topic_name, msg)
                 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)
-                        try:
-                            assert success
-                        except AssertionError:
-                            return response.json(10044)
-                        time.sleep(0.3)
-                    smart_scene_qs.update(is_enable=False)
-
+                    SmartScene.objects.filter(sub_device_id=sub_device_id, is_enable=True).update(is_enable=False)
             return response.json(0)
         except Exception as e:
-            return response.json(500, repr(e))
+            return response.json(500, 'error_line:{}, error_msg:{}'.format(e.__traceback__.tb_lineno, repr(e)))
 
     @staticmethod
     def get_sensor_list(request_dict, response):
@@ -554,14 +532,14 @@ class GatewaySubDeviceView(View):
                 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',
+                                                                                          'device_type', 'ieee_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'],
+                        'srcAddr': device_qs[0]['ieee_addr'],
                         'status': device_qs[0]['status'],
                         'createdTime': device_qs[0]['created_time'],
                         'roomName': room_name,
@@ -570,7 +548,7 @@ class GatewaySubDeviceView(View):
                     device_list.append(res)
             return response.json(0, device_list)
         except Exception as e:
-            return response.json(500, repr(e))
+            return response.json(500, 'error_line:{}, error_msg:{}'.format(e.__traceback__.tb_lineno, repr(e)))
 
     @staticmethod
     def get_device_list(request_dict, response):
@@ -589,19 +567,21 @@ class GatewaySubDeviceView(View):
         try:
             family_room_device_qs = FamilyRoomDevice.objects.filter(family_id=family_id, sub_device=0,
                                                                     device__Type=200).values(
-                'device_id', 'device__NickName').order_by('-device__data_joined')
+                'device_id', 'device__NickName', 'device__serial_number').order_by('-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:
+                device_id = item['device_id']
+                serial_number = item['device__serial_number']
                 device_dict = {
-                    'deviceId': item['device_id'],
                     'deviceType': 200,
-                    'deviceNickName': item['device__NickName'],
+                    'deviceId': device_id,
+                    'deviceNickName': item['device__NickName']
                 }
                 sub_device = []
                 family_room_sub_device_qs = FamilyRoomDevice.objects.filter(Q(family_id=family_id), ~Q(sub_device=0),
-                                                                            Q(device_id=item['device_id'])).values(
+                                                                            Q(device_id=device_id)).values(
                     'sub_device', 'room_id').order_by('sort')
                 if family_room_sub_device_qs.exists():
                     for each in family_room_sub_device_qs:
@@ -609,7 +589,7 @@ class GatewaySubDeviceView(View):
                         room_name = room_qs[0]['name'] if room_qs.exists() else ''
                         device_qs = GatewaySubDevice.objects.filter(id=each['sub_device']).values('id', 'nickname',
                                                                                                   'device_type',
-                                                                                                  'src_addr',
+                                                                                                  'ieee_addr',
                                                                                                   'status',
                                                                                                   'created_time')
                         if device_qs.exists():
@@ -617,17 +597,53 @@ class GatewaySubDeviceView(View):
                                 'gatewaySubId': device_qs[0]['id'],
                                 'nickName': device_qs[0]['nickname'],
                                 'deviceType': device_qs[0]['device_type'],
-                                'srcAddr': device_qs[0]['src_addr'],
+                                'srcAddr': device_qs[0]['ieee_addr'],
                                 'status': device_qs[0]['status'],
                                 'createdTime': device_qs[0]['created_time'],
                                 'roomName': room_name,
-                                'familyId': family_id
+                                'familyId': family_id,
+                                'serialNumber': serial_number
                             })
                     device_dict['subDevice'] = sub_device
                     device_list.append(device_dict)
             return response.json(0, device_list)
         except Exception as e:
-            return response.json(500, repr(e))
+            return response.json(500, 'error_line:{}, error_msg:{}'.format(e.__traceback__.tb_lineno, repr(e)))
+
+    @staticmethod
+    def update_online_status(request_dict, response):
+        """
+        更新子设备在线状态
+        @param request_dict: 请求参数
+        @request_dict online: 在线状态, 0:离线, 1:在线, 2:复位
+        @request_dict ieee_addr: 长地址
+        @param response: 响应对象
+        @return: response
+        """
+        online = request_dict.get('online', None)
+        ieee_addr = request_dict.get('ieee_addr', None)
+
+        if not all([online, ieee_addr]):
+            return response.json(444, {'error param': 'online or ieee_addr'})
+        online = int(online)
+        try:
+            if online == 2:     # 复位删除设备
+                gateway_sub_device_qs = GatewaySubDevice.objects.filter(ieee_addr=ieee_addr)
+                if not gateway_sub_device_qs.exists():
+                    return response.json(0)
+                sub_device_id = gateway_sub_device_qs.values('id')[0]['id']
+                # 删除设备信息,场景信息,场景日志
+                with transaction.atomic():
+                    gateway_sub_device_qs.delete()
+                    SmartScene.objects.filter(sub_device_id=sub_device_id).delete()
+                    SceneLog.objects.filter(sub_device_id=sub_device_id).delete()
+            else:
+                GatewaySubDevice.objects.filter(ieee_addr=ieee_addr).update(status=online)
+            return response.json(0)
+        except Exception as e:
+            return response.json(500, 'error_line:{}, error_msg:{}'.format(e.__traceback__.tb_lineno, repr(e)))
+
+
 #
 #                   ___====-_  _-====___
 #             _--^^^#####//      \\#####^^^--_

+ 52 - 0
Model/models.py

@@ -3552,6 +3552,58 @@ class SocketSchedule(models.Model):
         verbose_name_plural = verbose_name
 
 
+class SwitchInfo(models.Model):
+    id = models.AutoField(primary_key=True, verbose_name='自增id')
+    device_id = models.CharField(max_length=32, default='', verbose_name='设备id')
+    model = models.CharField(max_length=32, default='', verbose_name='型号')
+    hardware_version = models.CharField(max_length=32, default='', verbose_name='硬件版本')
+    firmware_version = models.CharField(max_length=32, default='', verbose_name='固件版本')
+    mac = models.CharField(max_length=32, default='', verbose_name='mac地址')
+
+    class Meta:
+        db_table = 'switch_info'
+        verbose_name = '智能开关信息'
+        verbose_name_plural = verbose_name
+
+
+class SwitchDimmingSettings(models.Model):
+    id = models.AutoField(primary_key=True, verbose_name='自增id')
+    device_id = models.CharField(max_length=32, default='', verbose_name='设备id')
+    click_turn_on_speed = models.SmallIntegerField(default=0, verbose_name='单击开启速度')
+    click_turn_off_speed = models.SmallIntegerField(default=0, verbose_name='单击关闭速度')
+    double_click = models.CharField(max_length=8, default='', verbose_name='双击')  # 0: 无, 1: 缓慢开/关, x%: 预设亮度
+    press = models.CharField(max_length=8, default='', verbose_name='长按')  # 0: 无, 1: 缓慢开/关, x%: 预设亮度
+    double_press_click_turn_on_speed = models.SmallIntegerField(default=0, verbose_name='双击/长按开启速度')
+    double_press_click_turn_off_speed = models.SmallIntegerField(default=0, verbose_name='双击/长按单击关闭速度')
+    led = models.BooleanField(default=False, verbose_name='LED指示灯')  # True: 开, False: 关
+    dimming_correction = models.CharField(max_length=8, default='', verbose_name='调光校正')
+
+    class Meta:
+        db_table = 'switch_dimming_settings'
+        verbose_name = '智能开关调光设置'
+        verbose_name_plural = verbose_name
+
+
+class SwitchChronopher(models.Model):
+    id = models.AutoField(primary_key=True, verbose_name='自增id')
+    device_id = models.CharField(max_length=32, default='', verbose_name='设备id')
+    time_type_radio = models.SmallIntegerField(default=0, verbose_name='切换时间点/时间段')  # 1: 按时间点, 2: 按时间段
+    time_point = models.IntegerField(default=0, verbose_name='时间点')
+    time_quantum_start_time = models.IntegerField(default=0, verbose_name='时间段开始时间')
+    time_quantum_end_time = models.IntegerField(default=0, verbose_name='时间段结束时间')
+    time_point_device_will_doing = models.CharField(max_length=8, default='',
+                                                    verbose_name='设备将会')  # 0: 开启, 1: 关闭, x%: 预设亮度
+    time_quantum_device_will_doing = models.SmallIntegerField(default=0,
+                                                              verbose_name='设备将会')  # 0: 开启, 1: 关闭, x: 开启/关闭切换间隔
+    slow_open_or_close_speed = models.SmallIntegerField(default=0, verbose_name='缓慢开/关速度')
+    repeat = models.SmallIntegerField(default=0, verbose_name=u'重复周期')
+
+    class Meta:
+        db_table = 'switch_chronopher'
+        verbose_name = '定时计划'
+        verbose_name_plural = verbose_name
+
+
 class ExchangeCode(models.Model):
     id = models.AutoField(primary_key=True)
     code = models.CharField(max_length=32, unique=True, verbose_name='兑换码')