Эх сурвалжийг харах

智能开关计时器功能

peng 1 жил өмнө
parent
commit
13225d1899

+ 108 - 17
Controller/SensorGateway/SmartSwitchController.py

@@ -6,9 +6,8 @@
 """
 import datetime
 import json
-import os
-import threading
 import time
+
 from django.views import View
 
 from Model.models import SwitchDimmingSettings, SwitchChronopher, Device_Info, SceneLog, FamilyRoomDevice, \
@@ -21,6 +20,7 @@ from Ansjer.config import LOGGER
 
 APSCHEDULER_TOPIC_NAME = 'loocam/switch/time_scheduling/{}'  # 排程主题
 RESET_SWITCH_TOPIC_NAME = 'loocam/smart-switch/{}'  # 重置设备
+TIMER_TOPIC_NAME = 'loocam/switch/count_down/{}'  # 计时器主题
 MQTT_TASK = 'Controller.CeleryTasks.tasks.send_mqtt'
 
 
@@ -48,14 +48,18 @@ class SmartSwitchView(View):
                 return response.json(token_code)
             if operation == 'get-dimming-setting':  # 获取智能开关调光设置
                 return self.get_dimming_setting(request_dict, response)
-            elif operation == 'get-chronopher-setting':  # 获取定时计划
+            elif operation == 'get-chronopher-setting':  # 获取排程计划
                 return self.get_chronopher_setting(request_dict, response)
-            elif operation == 'add-or-edit-chronopher':  # 添加/编辑定时计划
+            elif operation == 'add-or-edit-chronopher':  # 添加/编辑排程计划
                 return self.add_or_edit_chronopher(request_dict, response)
-            elif operation == 'edit-chronopher-status':  # 修改定时计划状态
+            elif operation == 'edit-chronopher-status':  # 修改排程计划状态
                 return self.edit_chronopher_status(request_dict, response)
-            elif operation == 'delete-chronopher':  # 删除定时计划
+            elif operation == 'delete-chronopher':  # 删除排程计划
                 return self.delete_chronopher(request_dict, response)
+            elif operation == 'get-timer-setting':  # 获取计时器
+                return self.get_timer_setting(request_dict, response)
+            elif operation == 'add-or-edit-timer':  # 添加/编辑计时器
+                return self.add_or_edit_timer(request_dict, response)
             elif operation == 'edit-dimming-correction':  # 设置调光校正
                 return self.edit_dimming_correction(request_dict, response)
             elif operation == 'edit-dimming-setting':  # 修改智能开关调光设置
@@ -163,7 +167,7 @@ class SmartSwitchView(View):
     @staticmethod
     def get_chronopher_setting(request_dict, response):
         """
-        获取定时计划设置
+        获取排程计划设置
         @param request_dict: 请求参数
         @request_dict deviceId: 设备id
         @param response: 响应对象
@@ -197,10 +201,10 @@ class SmartSwitchView(View):
     @staticmethod
     def add_or_edit_chronopher(request_dict, response):
         """
-        添加/编辑定时计划
+        添加/编辑排程计划
         @param request_dict: 请求参数
         @request_dict deviceId: 设备id
-        @request_dict chronopherId: 定时计划id
+        @request_dict chronopherId: 排程计划id
         @request_dict timeTypeRadio: 切换时间点/时间段
         @request_dict timePoint: 时间点
         @request_dict timeQuantumStartTime: 时间段开始时间
@@ -272,7 +276,7 @@ class SmartSwitchView(View):
                     switch_qs = SwitchChronopher.objects.create(**chronopher_data)
                     chronopher_id = switch_qs.id
 
-                # 设置定时任务
+                # 设置排程任务
                 serial_number = device_qs[0]['serial_number']
                 user_id = device_qs[0]['userID']
                 tz = CommonService.get_user_tz(user_id)
@@ -333,10 +337,10 @@ class SmartSwitchView(View):
     @staticmethod
     def edit_chronopher_status(request_dict, response):
         """
-        修改定时计划状态
+        修改排程计划状态
         @param request_dict: 请求参数
         @request_dict deviceId: 设备id
-        @request_dict chronopherId: 定时计划id
+        @request_dict chronopherId: 排程计划id
         @request_dict isExecute: 修改状态
         @param response: 响应对象
         @return: response
@@ -365,10 +369,10 @@ class SmartSwitchView(View):
     @staticmethod
     def delete_chronopher(request_dict, response):
         """
-        删除定时计划
+        删除排程计划
         @param request_dict: 请求参数
         @request_dict deviceId: 设备id
-        @request_dict chronopherId: 定时计划id
+        @request_dict chronopherId: 排程计划id
         @param response: 响应对象
         @return: response
         """
@@ -382,7 +386,7 @@ class SmartSwitchView(View):
             if not delete_flag[0]:
                 return response.json(173)
             celery_obj = CeleryBeatObj()
-            celery_obj.del_task('switchchronopher_{}'.format(chronopher_id))  # 删除定时任务
+            celery_obj.del_task('switchchronopher_{}'.format(chronopher_id))  # 删除排程任务
             celery_obj.del_task('switchchronopher_{}_1'.format(chronopher_id))
             celery_obj.del_task('switchchronopher_{}_2'.format(chronopher_id))
             return response.json(0)
@@ -390,6 +394,93 @@ class SmartSwitchView(View):
             print(e)
             return response.json(500, 'error_line:{}, error_msg:{}'.format(e.__traceback__.tb_lineno, repr(e)))
 
+    @staticmethod
+    def get_timer_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:
+            key = 'Switch-Timer-' + device_id
+            redis_obj = RedisObject()
+            timer_info = redis_obj.get_all_hash_data(key)
+            if not timer_info:
+                res = {'timePoint': -1, 'countdownTime': -1, 'timePointDeviceWillDoing': -1, 'timerStatus': -1}
+            else:
+                res = timer_info
+            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_or_edit_timer(request_dict, response):
+        """
+        添加/编辑计时器
+        @param request_dict: 请求参数
+        @request_dict deviceId: 设备id
+        @request_dict chronopherId: 排程计划id
+        @request_dict CountdownTime: 倒计时时间(秒)
+        @request_dict timePointDeviceWillDoing: 设备将会
+        @request_dict timerStatus: 计时器状态
+        @param response: 响应对象
+        @return: response
+        """
+        is_edit = request_dict.get('isEdit', None)
+        device_id = request_dict.get('deviceId', None)
+        countdown_time = request_dict.get('countdownTime', None)
+        time_point_device_will_doing = request_dict.get('timePointDeviceWillDoing', None)
+        timer_status = request_dict.get('timerStatus', None)
+
+        if not all([device_id, countdown_time, time_point_device_will_doing]):
+            return response.json(444, {'param': 'deviceId, countdownTime, timePointDeviceWillDoing'})
+        device_qs = Device_Info.objects.filter(id=device_id).values('serial_number', 'userID')
+        if not device_qs.exists():
+            return response.json(173)
+        try:
+            now_time = int(time.time())
+            countdown_time = int(countdown_time)
+            serial_number = device_qs[0]['serial_number']
+            user_id = device_qs[0]['userID']
+            tz = CommonService.get_user_tz(user_id)
+            celery_obj = CeleryBeatObj()
+            redis_obj = RedisObject()
+            task_id = 'switchtimer_{}'.format(device_id)
+            topic_name = TIMER_TOPIC_NAME.format(serial_number)
+            key = 'Switch-Timer-' + device_id
+            implement_time = now_time + countdown_time
+            redis_dict = {'timePoint': implement_time,
+                          'countdownTime': countdown_time,
+                          'timePointDeviceWillDoing': time_point_device_will_doing,
+                          'timerStatus': timer_status}
+            with transaction.atomic():
+                if is_edit:
+                    celery_obj.del_task(task_id)
+                    if not timer_status:
+                        return response.json(444, {'param': 'timerStatus'})
+                    timer_status = int(timer_status)
+                    if timer_status == 0:  # 暂停计时器
+                        redis_dict['timePoint'] = -1
+                        redis_obj.set_hash_data(key, redis_dict)
+                        redis_obj.set_persist(key)
+                        return response.json(0)
+                redis_obj.set_hash_data(key, redis_dict)
+                redis_obj.set_expire(key, countdown_time)
+                msg = {'device_switch': time_point_device_will_doing, 'implement_time': implement_time,
+                       'task_id': task_id}
+                celery_obj.creat_clocked_task(task_id, MQTT_TASK, implement_time, tz,
+                                              args=[serial_number, topic_name, msg, task_id])
+                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 create_chronopher_log(request_dict, response):
         """
@@ -498,7 +589,7 @@ class SmartSwitchView(View):
                 celery_obj = CeleryBeatObj()
                 for chronopher in chronopher_qs:
                     chronopher_id = chronopher.id
-                    celery_obj.del_task('switchchronopher_{}'.format(chronopher_id))  # 删除定时任务
+                    celery_obj.del_task('switchchronopher_{}'.format(chronopher_id))  # 删除排程任务
                     celery_obj.del_task('switchchronopher_{}_1'.format(chronopher_id))
                     celery_obj.del_task('switchchronopher_{}_2'.format(chronopher_id))
                 chronopher_qs.delete()
@@ -524,7 +615,7 @@ class SmartSwitchView(View):
                 celery_obj = CeleryBeatObj()
                 for chronopher in chronopher_qs:
                     chronopher_id = chronopher.id
-                    celery_obj.del_task('switchchronopher_{}'.format(chronopher_id))  # 删除定时任务
+                    celery_obj.del_task('switchchronopher_{}'.format(chronopher_id))  # 删除排程任务
                     celery_obj.del_task('switchchronopher_{}_1'.format(chronopher_id))
                     celery_obj.del_task('switchchronopher_{}_2'.format(chronopher_id))
                 chronopher_qs.delete()

+ 0 - 1
Model/models.py

@@ -4525,7 +4525,6 @@ class SwitchDimmingSettings(models.Model):
 class SwitchChronopher(models.Model):
     id = models.AutoField(primary_key=True, verbose_name='自增id')
     device_id = models.CharField(max_length=32, default='', verbose_name='设备id')
-    chronopher_type = models.SmallIntegerField(default=0, verbose_name='任务类型')  # 0: 排程任务, 1: 计时器任务
     time_type_radio = models.SmallIntegerField(default=1, verbose_name='切换时间点/时间段')  # 1: 按时间点, 2: 按时间段
     time_point = models.IntegerField(default=0, verbose_name='时间点时间戳')
     time_quantum_start_time = models.IntegerField(default=0, verbose_name='时间段开始时间')

+ 12 - 2
Object/CeleryBeatObject.py

@@ -62,8 +62,18 @@ class CeleryBeatObj:
             time_stamp = CommonService.convert_to_timestamp(timezone_offset, time_string)
         # 时间戳转为东八区的时间字符串
         clocked_time = CommonService.get_date_from_timestamp(time_stamp, 8)
-        schedule, _ = ClockedSchedule.objects.get_or_create(clocked_time=clocked_time)
-        PeriodicTask.objects.create(clocked=schedule, one_off=True, name=name, task=task, args=args, kwargs=kwargs)
+        periodic_task = PeriodicTask.objects.filter(name=name)
+        if periodic_task.exists():
+            periodic_task_qs = periodic_task[0]
+            clocked_id = periodic_task_qs.clocked_id
+            ClockedSchedule.objects.filter(id=clocked_id).update(clocked_time=clocked_time)
+            periodic_task_qs.task = task
+            periodic_task_qs.args = args
+            periodic_task_qs.kwargs = kwargs
+            periodic_task_qs.save()
+        else:
+            schedule, _ = ClockedSchedule.objects.get_or_create(clocked_time=clocked_time)
+            PeriodicTask.objects.create(clocked=schedule, one_off=True, name=name, task=task, args=args, kwargs=kwargs)
 
     @staticmethod
     def creat_crontab_task(

+ 6 - 1
Object/RedisObject.py

@@ -1,5 +1,7 @@
 import redis
 from Ansjer.config import SERVER_HOST
+
+
 # 本地调试把注释打开
 # SERVER_HOST = '127.0.0.1'
 
@@ -107,4 +109,7 @@ class RedisObject:
             return False
 
     def get_all_hash_data(self, key):
-        return self.CONN.hgetall(key)
+        return self.CONN.hgetall(key)
+
+    def set_persist(self, key):
+        return self.CONN.persist(key)