# -*- encoding: utf-8 -*- """ @File : SmartSocketController.py @Time : 2023/3/17 11:52 @Author : stephen @Email : zhangdongming@asj6.wecom.work @Software: PyCharm """ import logging import time from django.db import transaction from django.http import QueryDict from django.views import View from Model.models import SocketInfo, SocketSchedule, Device_Info from Object.ResponseObject import ResponseObject from Object.TokenObject import TokenObject from Service.CommonService import CommonService LOGGER = logging.getLogger('info') SOCKET_TOPIC_NAME = 'loocam/smart-socket/{}' # 插座发布消息主题(因设备当前版本只能订阅一个主题) class SmartSocketView(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 delete(self, request, *args, **kwargs): request.encoding = 'utf-8' operation = kwargs.get('operation') delete = QueryDict(request.body) if not delete: delete = request.GET return self.validation(delete, request, operation) def put(self, request, *args, **kwargs): request.encoding = 'utf-8' operation = kwargs.get('operation') put = QueryDict(request.body) return self.validation(put, request, operation) def validation(self, request_dict, request, operation): token = TokenObject(request.META.get('HTTP_AUTHORIZATION')) lang = request_dict.get('lang', 'cn') response = ResponseObject(lang) if token.code != 0: return response.json(token.code) if operation == 'addSwitch': # 添加插座开关 return self.add_switch(request_dict, response) elif operation == 'addCountDown': # 添加插座倒计时 return self.add_count_down(request_dict, response) elif operation == 'addSchedule': # 添加插座排程 return self.save_socket_schedule(request_dict, response) return response.json(404) @staticmethod def get_serial_number_by_device_id(deviceId): """ 根据设备ID获取序列号 """ device_info = Device_Info.objects.get(id=deviceId) return device_info.serial_number @classmethod def add_switch(cls, request_dict, response): """ 添加开关 """ device_id = request_dict.get('deviceId', None) status = request_dict.get('status', None) if not all([device_id, status]): return response.json(444) serial_number = cls.get_serial_number_by_device_id(device_id) # 保存数据库并下发MQTT消息到插座设备 result = cls.save_socket_switch(device_id, serial_number, int(status)) if not result: return response.json(177) return response.json(0) @staticmethod def save_socket_switch(device_id, serial_number, status, type_switch=0): """ 保存插座开关信息 @param device_id: 设备ID @param serial_number: 序列号 @param status: 状态 0关,1开 @param type_switch: 0:总开关,1倒计时开关 @return: True | False """ if not device_id: return False socket_info_qs = SocketInfo.objects.filter(device_id=device_id, type_switch=type_switch) now_time = int(time.time()) try: with transaction.atomic(): # 创建插座开关信息 if not socket_info_qs.exists(): socket_dict = {"device_id": device_id, "serial_number": serial_number, "status": status, "type_switch": type_switch, "created_time": now_time, "updated_time": now_time, "online": True} SocketInfo.objects.create(**socket_dict) return True if socket_info_qs.first().status == status: return True socket_info_qs.update(status=status, updated_time=now_time) # 主题名称 topic_name = SOCKET_TOPIC_NAME.format(serial_number) # 发布消息内容 msg = {'type': 1, 'data': {'deviceSwitch': status}} result = CommonService.req_publish_mqtt_msg(serial_number, topic_name, msg) LOGGER.info('智能插座开关设置发布MQTT消息结果{}'.format(result)) return True except Exception as e: LOGGER.info('智能插座异常,errLine:{}, errMsg:{}'.format(e.__traceback__.tb_lineno, repr(e))) return False @classmethod def add_count_down(cls, request_dict, response): """ 添加倒计时 """ device_id = request_dict.get('deviceId', None) status = request_dict.get('status', None) start = request_dict.get('start', None) count_down_time = request_dict.get('countDownTime', None) if not all([device_id, status, count_down_time]): return response.json(444) serial_number = cls.get_serial_number_by_device_id(device_id) # 保存数据库并下发MQTT消息到插座设备 result = cls.save_socket_count_down(device_id, serial_number, int(status), int(start), int(count_down_time)) if not result: return response.json(177) return response.json(0) @staticmethod def save_socket_count_down(device_id, serial_number, status, start, count_down_time, type_switch=1): """ 保存插座倒计时信息 @param count_down_time: 倒计时时间戳 @param start: 是否启动倒计时 0:关闭,1:开始 @param device_id: 设备ID @param serial_number: 序列号 @param status: 倒计时电源状态 0关,1开 @param type_switch: 0:总开关,1倒计时开关 @return: """ if not device_id: return False socket_info_qs = SocketInfo.objects.filter(device_id=device_id, type_switch=type_switch) now_time = int(time.time()) try: with transaction.atomic(): # 创建插座倒计时信息 if not socket_info_qs.exists(): socket_dict = {"device_id": device_id, "serial_number": serial_number, "status": status, "type_switch": type_switch, "created_time": now_time, "updated_time": now_time, "online": True, "count_down_time": count_down_time} socket_info_qs = SocketInfo.objects.create(**socket_dict) count_down_id = socket_info_qs.id else: socket_info_qs.update(status=status, count_down_time=count_down_time, updated_time=now_time) count_down_id = socket_info_qs.first().id # 主题名称 topic_name = SOCKET_TOPIC_NAME.format(serial_number) # 发布消息内容 msg = {'type': 2, 'data': {'powerType': status, 'countDownId': count_down_id, 'time': count_down_time, 'start': start}} result = CommonService.req_publish_mqtt_msg(serial_number, topic_name, msg) LOGGER.info('智能插座倒计时发布MQTT消息结果{}'.format(result)) return True except Exception as e: LOGGER.info('智能插座异常,errLine:{}, errMsg:{}'.format(e.__traceback__.tb_lineno, repr(e))) return False @classmethod def save_socket_schedule(cls, request_dict, response): """ 插座添加排程 """ try: device_id = request_dict.get('deviceId', None) task_type = request_dict.get('timeType', None) start_time = request_dict.get('startTime', None) end_time = request_dict.get('endTime', None) repeat = request_dict.get('repeat', None) task_id = request_dict.get('taskId', None) device_switch = request_dict.get('deviceSwitch', None) task_switch = request_dict.get('taskSwitch', None) if not all([task_type, start_time, repeat, device_switch, task_switch]): return response.json(444) device_switch = int(device_switch) task_switch = int(task_switch) now_time = int(time.time()) data = {'time_type': int(task_type), 'start_time': int(start_time), 'repeat': int(repeat), 'switch_status': True if device_switch == 1 else False, 'task_status': True if task_switch == 1 else False} serial_number = cls.get_serial_number_by_device_id(device_id) if task_id: # 修改排程 task_id = int(task_id) socket_schedule_qs = SocketSchedule.objects.filter(id=task_id) if not socket_schedule_qs.exists(): return response.json(174) if end_time: data['end_time'] = int(end_time) data['updated_time'] = now_time socket_schedule_qs.update(**data) else: # 添加排程 data['device_id'] = device_id data['serial_number'] = serial_number data['updated_time'] = now_time data['created_time'] = now_time socket_schedule = SocketSchedule.objects.create(**data) task_id = socket_schedule.id # 讲排程任务下发给设备 cls.send_socket_schedule(serial_number, task_id, int(task_type), int(start_time), int(end_time), int(repeat), device_switch, task_switch) return response.json(0) except Exception as e: LOGGER.info('智能插座异常,errLine:{}, errMsg:{}'.format(e.__traceback__.tb_lineno, repr(e))) return False @staticmethod def send_socket_schedule(serial_number, task_id, time_type, start_time, end_time, repeat, device_switch, task_switch): """ 排程下发设备 @param serial_number: 序列号 @param task_id: 当前排程任务id @param time_type: 任务类型 0:设定时间,1:设定时间段 @param start_time: 开启时间 @param end_time: 结束时间 @param repeat: 重复日期 @param device_switch: 任务执行后期望设备状态,0:关闭,1:开启 @param task_switch: 任务执行状态 0:不执行,1:执行 @return: True | False """ msg = { 'type': 3, 'data': {'taskId': task_id, 'timeType': time_type, 'startTime': start_time, 'endTime': end_time, 'repeat': repeat, 'deviceSwitch': device_switch, 'taskSwitch': task_switch} } # 主题名称 topic_name = SOCKET_TOPIC_NAME.format(serial_number) result = CommonService.req_publish_mqtt_msg(serial_number, topic_name, msg) LOGGER.info('智能插座排程任务发布MQTT消息结果{}'.format(result)) return result