| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933 | 
							- # -*- encoding: utf-8 -*-
 
- """
 
- @File    : SmartSocketController.py
 
- @Time    : 2023/3/17 11:52
 
- @Author  : stephen
 
- @Email   : zhangdongming@asj6.wecom.work
 
- @Software: PyCharm
 
- """
 
- import calendar
 
- import datetime
 
- import logging
 
- import time
 
- import requests
 
- from dateutil.parser import parse
 
- from django.db import transaction, connections
 
- from django.db.models import Sum, Count
 
- from django.http import QueryDict
 
- from django.views import View
 
- from Model.models import SocketInfo, SocketSchedule, Device_Info, SocketPowerStatistics, SceneLog, FamilyRoomDevice
 
- from Object.ResponseObject import ResponseObject
 
- from Object.utils import LocalDateTimeUtil
 
- 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):
 
-         ResponseObject('cn')
 
-         if operation == 'savePowerStatistics':  # 保存电量上报统计
 
-             return self.save_power_statistics(request_dict, ResponseObject('cn'))
 
-         elif operation == 'reset':  # 设备复位
 
-             return self.socket_reset(request_dict, ResponseObject('cn'))
 
-         elif operation == 'alexa-socket-switch':  # 新增alexa智能开关
 
-             return self.alexa_socket_switch(request_dict, ResponseObject('cn'))
 
-         elif operation == 'getSocketState':  # 获取alexa智能开关状态
 
-             return self.get_socket_state(request_dict, ResponseObject('cn'))
 
-         elif operation == 'socketPush':  # 插座推送
 
-             return self.socket_msg_push(request_dict, ResponseObject('cn'))
 
-         token_code, user_id, response = CommonService \
 
-             .verify_token_get_user_id(request_dict, request)
 
-         if token_code != 0:
 
-             return response.json(token_code)
 
-         if operation == 'saveSwitch':  # 添加插座开关
 
-             return self.save_switch(request_dict, response)
 
-         elif operation == 'saveCountDown':  # 添加插座倒计时
 
-             return self.save_count_down(request_dict, response)
 
-         elif operation == 'saveSchedule':  # 添加插座排程
 
-             return self.save_socket_schedule(request_dict, response)
 
-         elif operation == 'get-all-scene':  # 统计智能插座电量
 
-             return self.get_all_scene(request_dict, response)
 
-         elif operation == 'get-socket-schedule':  # 智能插座排程记录查询
 
-             return self.get_socket_schedule(request_dict, response)
 
-         elif operation == 'get-log':  # 智能插座开关日志记录查询
 
-             return self.get_log(request_dict, response)
 
-         elif operation == 'del-socket-schedule':  # 批量刪除排程
 
-             return self.del_socket_schedule(request_dict, response, user_id)
 
-         elif operation == 'get-unit-scene':  # 查詢設備每日/月用電量
 
-             return self.get_unit_scene(request_dict, response)
 
-         elif operation == 'get-schedule-data':  # 查询插座记录日期
 
-             return self.get_schedule_data(request_dict, response)
 
-         return response.json(404)
 
-     @classmethod
 
-     def socket_reset(cls, request_dict, response):
 
-         """
 
-         智能插座复位删除数据
 
-         """
 
-         try:
 
-             with transaction.atomic():
 
-                 serial_number = request_dict.get('serialNumber', None)
 
-                 status = request_dict.get('status', None)  # 设备当前状态0:关, 1:开, 2:离线
 
-                 if not all([serial_number, status]):
 
-                     return response.json(444, {'error': 'serialNumber and status'})
 
-                 socket_info_qs = SocketInfo.objects.filter(serial_number=serial_number, type_switch=0)
 
-                 if not socket_info_qs.exists():
 
-                     return response.json(173)
 
-                 device_id = socket_info_qs.first().device_id
 
-                 if socket_info_qs.first().status == 1:  # 设备电源开时 恢复为关闭状态
 
-                     socket_info_qs.update(status=0, updated_time=int(time.time()))
 
-                 # 删除插座电量统计
 
-                 SocketPowerStatistics.objects.filter(device_id=device_id).delete()
 
-                 # 删除插座排程
 
-                 SocketSchedule.objects.filter(device_id=device_id).delete()
 
-                 # 删除插座开关日志
 
-                 SceneLog.objects.filter(device_id=serial_number).delete()
 
-                 # 离线状态下只删除设备电量, 排程和开关日志
 
-                 if int(status) != 2:
 
-                     # 删除插座倒计时
 
-                     SocketInfo.objects.filter(device_id=device_id).delete()
 
-                     # 删除设备管理家庭接口
 
-                     FamilyRoomDevice.objects.filter(device_id=device_id).delete()
 
-                     # 删除设备
 
-                     Device_Info.objects.filter(id=device_id).delete()
 
-                     # alexa删除插座
 
-                     cls.delete_alexa_socket(serial_number)
 
-                 LOGGER.info('智能插座{}设备已复位'.format(serial_number))
 
-                 return response.json(0)
 
-         except Exception as e:
 
-             LOGGER.info('插座复位删除数据异常,errLine:{}, errMsg:{}'.format(e.__traceback__.tb_lineno, repr(e)))
 
-             return response.json(177)
 
-     @classmethod
 
-     def save_power_statistics(cls, request_dict, response):
 
-         """
 
-         保存设备上报电量统计
 
-         """
 
-         try:
 
-             serial_number = request_dict.get('serialNumber', None)
 
-             watt = request_dict.get('electricity', 0.00)  # 功率
 
-             power = request_dict.get('power', 0.00)  # 负载功率
 
-             # 在线时长秒
 
-             accumulated_time = request_dict.get('accumulatedTime', None)
 
-             device_time = request_dict.get('deviceTime', None)
 
-             if not all([serial_number, watt, power, accumulated_time, device_time]):
 
-                 return response.json(444)
 
-             watt = float(watt)
 
-             power = float(power)
 
-             accumulated_time = int(accumulated_time)
 
-             #  判断上报数据是否为负数
 
-             number_list = [watt, power, accumulated_time]
 
-             number = CommonService.negative_number_judgment(number_list)
 
-             if not number:
 
-                 if watt < 0:
 
-                     watt = 0
 
-                 if power < 0:
 
-                     power = 0
 
-                 if accumulated_time < 0:
 
-                     accumulated_time = 0
 
-             now_time = int(time.time())
 
-             LOGGER.info('{}上报电量统计data:{}'.format(serial_number, request_dict))
 
-             start_time, end_time = LocalDateTimeUtil.get_today_date(True)
 
-             # 查询当前序列号当天是否有上传过电量统计
 
-             power_qs = SocketPowerStatistics.objects.filter(serial_number=serial_number,
 
-                                                             created_time__gt=start_time,
 
-                                                             created_time__lte=end_time)
 
-             data = {
 
-                 'power': power,
 
-                 'updated_time': now_time,
 
-                 'watt': watt
 
-             }
 
-             if not power_qs.exists():  # 添加插座上报电量统计
 
-                 socket_info_qs = SocketInfo.objects.filter(serial_number=serial_number).values('device_id')
 
-                 if not socket_info_qs.exists():
 
-                     return response.json(173)
 
-                 data['device_id'] = socket_info_qs[0]['device_id']
 
-                 data['created_time'] = now_time
 
-                 data['serial_number'] = serial_number
 
-                 data['electricity'] = cls.calculated_power(watt, accumulated_time)
 
-                 data['accumulated_time'] = accumulated_time
 
-                 SocketPowerStatistics.objects.create(**data)
 
-                 return response.json(0)
 
-             power_vo = power_qs.first()
 
-             # 累加在线时间目前是以分钟为单位
 
-             data['accumulated_time'] = power_vo.accumulated_time + accumulated_time
 
-             # kwh 千瓦时
 
-             kilowatt_hour = cls.calculated_power(watt, accumulated_time)
 
-             data['electricity'] = kilowatt_hour + float(power_vo.electricity)
 
-             # 所消耗累计功率
 
-             data['watt'] = float(power_vo.watt) + watt
 
-             # 更新当天电量统计
 
-             power_qs.update(**data)
 
-             return response.json(0)
 
-         except Exception as e:
 
-             LOGGER.info('智能插座电量存库异常,errLine:{}, errMsg:{}'.format(e.__traceback__.tb_lineno, repr(e)))
 
-             return response.json(177)
 
-     @staticmethod
 
-     def calculated_power(watt, minute):
 
-         """
 
-         通过每分钟所消耗的功率(瓦)得到千瓦时kwh
 
-         """
 
-         if watt == 0 or watt < 0.1 or minute == 0:
 
-             return 0.00
 
-         hours = minute / 3600
 
-         kilowatt_hour = watt * hours / 1000
 
-         LOGGER.info('瓦计算得到千瓦时结果{}'.format(kilowatt_hour))
 
-         return kilowatt_hour
 
-     @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 save_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)
 
-         LOGGER.info('{}进入插座电源开关OR倒计时,类型:{}'.format(serial_number, 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:
 
-                     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(serial_number, result))
 
-                 return True
 
-         except Exception as e:
 
-             LOGGER.info('智能插座异常,errLine:{}, errMsg:{}'.format(e.__traceback__.tb_lineno, repr(e)))
 
-             return False
 
-     @classmethod
 
-     def save_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,
 
-                                    "start": True if start == 1 else False,
 
-                                    "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', 0)
 
-             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, end_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())
 
-             task_type = int(task_type)
 
-             end_time = int(end_time) if task_type == 2 else 0
 
-             data = {'time_type': 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'] = end_time
 
-                 data['updated_time'] = now_time
 
-                 socket_schedule_qs.update(**data)
 
-             else:
 
-                 # 查询是否已设置过当前排程
 
-                 socket_s_qs = SocketSchedule.objects.filter(device_id=device_id,
 
-                                                             start_time=int(start_time),
 
-                                                             end_time=end_time,
 
-                                                             time_type=task_type)
 
-                 if socket_s_qs.exists():
 
-                     return response.json(174)
 
-                 schedule_count = SocketSchedule.objects.filter(device_id=device_id).count()
 
-                 if schedule_count >= 20:
 
-                     return response.json(10061)
 
-                 # 添加排程
 
-                 data['device_id'] = device_id
 
-                 data['end_time'] = end_time
 
-                 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, task_type, int(start_time),
 
-                                          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(serial_number, result))
 
-         return result
 
-     # 以下是查询智能插座接口
 
-     @staticmethod
 
-     def get_all_scene(request_dict, response):
 
-         """
 
-         统计智能插座电量
 
-         @request_dict serialNumber: 序列号
 
-         @request_dict unit: 时间单位
 
-         @param request_dict: 请求数据
 
-         @param response: 响应
 
-         @return: response
 
-         """
 
-         serial_number = request_dict.get('serialNumber', None)
 
-         # 确定是否会传值
 
-         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') \
 
-             .order_by('-created_time')
 
-         if not all_socket_power_qs.exists():
 
-             return response.json(0, {})
 
-         try:
 
-             data = {}
 
-             # 设备累计电量
 
-             all_electricity = all_socket_power_qs.aggregate(total=Sum('electricity'))
 
-             data['electricityAll'] = round(all_electricity['total'], 1)
 
-             # 本月电费
 
-             nowTime = int(time.time())
 
-             nowTime = CommonService.timestamp_to_str(nowTime)
 
-             year, month = str(nowTime).split('-')[0], str(nowTime).split('-')[1]
 
-             end = calendar.monthrange(int(year), int(month))[1]
 
-             startTime_now = parse('%s-%s-01 00:00:00' % (year, month))
 
-             endTime_now = parse('%s-%s-%s 23:59:59' % (year, month, end))
 
-             startTime_now = CommonService.str_to_timestamp(str(startTime_now))
 
-             endTime_now = CommonService.str_to_timestamp(str(endTime_now))
 
-             electricity = all_socket_power_qs.filter(created_time__gte=startTime_now,
 
-                                                      created_time__lt=endTime_now).aggregate(
 
-                 total=Sum('electricity'))
 
-             if electricity['total'] is not None:
 
-                 data['electricityMonth'] = round(electricity['total'], 1)
 
-             else:
 
-                 data['electricityMonth'] = 0
 
-             # 获取当前日期
 
-             nowTime = int(time.time())
 
-             today = datetime.date.today()
 
-             #  今天开始时间
 
-             today_start_time = int(time.mktime(time.strptime(str(today), '%Y-%m-%d')))
 
-             today_socket_power_qs = all_socket_power_qs.filter(created_time__gte=today_start_time,
 
-                                                                created_time__lt=nowTime).values('electricity',
 
-                                                                                                 'accumulated_time',
 
-                                                                                                 'power',
 
-                                                                                                 'created_time')
 
-             # 当天使用电量
 
-             data['electricityToday'] = round(today_socket_power_qs[0]['electricity'],
 
-                                              1) if today_socket_power_qs.exists() else 0
 
-             # 当天累计时长
 
-             data['accumulated_time'] = today_socket_power_qs[0][
 
-                 'accumulated_time'] if today_socket_power_qs.exists() else 0
 
-             # 当前功率
 
-             data['power'] = round(today_socket_power_qs[0]['power'], 1) if today_socket_power_qs.exists() else 0
 
-             # 昨天使用电量
 
-             yesterday = today - datetime.timedelta(days=1)
 
-             # 昨天开始时间戳
 
-             yesterday_start_time = int(time.mktime(time.strptime(str(yesterday), '%Y-%m-%d')))
 
-             # 昨天结束时间戳
 
-             yesterday_end_time = int(time.mktime(time.strptime(str(today), '%Y-%m-%d'))) - 1
 
-             socket_qs = all_socket_power_qs.filter(created_time__gte=yesterday_start_time,
 
-                                                    created_time__lt=yesterday_end_time).values('electricity')
 
-             if socket_qs.exists():
 
-                 data['electricityYesterday'] = round(socket_qs[0]['electricity'], 1)
 
-             else:
 
-                 data['electricityYesterday'] = 0
 
-             return response.json(0, data)
 
-         except Exception as e:
 
-             return response.json(500, 'error_line:{}, error_msg:{}'.format(e.__traceback__.tb_lineno, repr(e)))
 
-     @staticmethod
 
-     def get_socket_schedule(request_dict, response):
 
-         """
 
-         智能插座排程记录查询
 
-         @param request_dict: 请求参数
 
-         @request_dict page: 页数
 
-         @request_dict size: 条数
 
-         @request_dict serialNumber: 设备序列号
 
-         @param response: 响应对象
 
-         @return: response
 
-         """
 
-         page = request_dict.get('pageNo', None)
 
-         size = request_dict.get('pageSize', None)
 
-         serial_number = request_dict.get('serialNumber', None)
 
-         if not all([page, size, serial_number]):
 
-             return response.json(444)
 
-         page, size = int(page), int(size)
 
-         socket_schedule_qs = SocketSchedule.objects.filter(serial_number=serial_number).values('switch_status',
 
-                                                                                                'start_time',
 
-                                                                                                'end_time',
 
-                                                                                                'repeat',
 
-                                                                                                'task_status',
 
-                                                                                                'time_type',
 
-                                                                                                'created_time',
 
-                                                                                                'updated_time',
 
-                                                                                                'device_id',
 
-                                                                                                'id').order_by(
 
-             '-created_time')[(page - 1) * size:page * size]
 
-         if not socket_schedule_qs.exists():
 
-             return response.json(0, [])
 
-         try:
 
-             schedule_list = []
 
-             for socket_schedule in socket_schedule_qs:
 
-                 schedule_list.append({
 
-                     'taskId': socket_schedule['id'],
 
-                     'deviceID': socket_schedule['device_id'],
 
-                     'serialNumber': serial_number,
 
-                     'timeType': socket_schedule['time_type'],
 
-                     'startTime': socket_schedule['start_time'],
 
-                     'endTime': socket_schedule['end_time'],
 
-                     'switchStatus': socket_schedule['switch_status'],
 
-                     'taskStatus': socket_schedule['task_status'],
 
-                     # 进制
 
-                     'repeat': socket_schedule['repeat'],
 
-                 })
 
-             return response.json(0, schedule_list)
 
-         except Exception as e:
 
-             return response.json(500, 'error_line:{}, error_msg:{}'.format(e.__traceback__.tb_lineno, repr(e)))
 
-     @staticmethod
 
-     def get_log(request_dict, response):
 
-         """
 
-         智能插座开关日志记录查询
 
-         @param request_dict: 请求参数
 
-         @request_dict page: 页数
 
-         @request_dict size: 条数
 
-         @request_dict serialNumber: 设备序列号
 
-         @request_dict startTime: 开始时间
 
-         @request_dict endTime: 结束时间
 
-         @param response: 响应对象
 
-         @return: response
 
-         # 日誌擦護用序列號查詢
 
-         """
 
-         page = request_dict.get('page', None)
 
-         size = request_dict.get('size', None)
 
-         serial_number = request_dict.get('serialNumber', None)
 
-         startTime = request_dict.get('startTime', None)
 
-         endTime = request_dict.get('endTime', None)
 
-         if not all([page, size, serial_number]):
 
-             return response.json(444, 'errno: page or size or serial_number')
 
-         page, size = int(page), int(size)
 
-         try:
 
-             sql_query = """
 
-                         SELECT DISTINCT 
 
-                             tasks,
 
-                             status,
 
-                             created_time
 
-                         FROM scene_log
 
-                         WHERE device_id = %s {}
 
-                         ORDER BY created_time DESC,id DESC
 
-                         LIMIT %s, %s;
 
-                     """
 
-             params = [serial_number]
 
-             if startTime is not None and endTime is not None:
 
-                 sql_query = sql_query.format(
 
-                     "AND created_time >= %s AND created_time < %s ")
 
-                 params.extend([startTime, endTime])
 
-             else:
 
-                 sql_query = sql_query.format(" ")
 
-             params.extend([(page - 1) * size, size])
 
-             cursor = connections['mysql02'].cursor()
 
-             cursor.execute(sql_query, params)
 
-             results = cursor.fetchall()
 
-             # 关闭游标
 
-             cursor.close()
 
-             connections.close_all()
 
-             log_list = []
 
-             for result in results:
 
-                 data = {
 
-                     'serialNumber': serial_number,
 
-                     'tasks': result[0] if result[0] else '',
 
-                     'status': result[1],
 
-                     'createdTime': result[2],
 
-                 }
 
-                 log_list.append(data)
 
-             return response.json(0, log_list)
 
-         except Exception as e:
 
-             return response.json(500, 'error_line:{}, error_msg:{}'.format(e.__traceback__.tb_lineno, repr(e)))
 
-     @classmethod
 
-     def splittings_time(cls, startTime, endTime, unit):
 
-         """
 
-         根據時間單位分割時間
 
-         """
 
-         diction = {}
 
-         time_list = []
 
-         # 开始时间
 
-         startTime = CommonService.timestamp_to_str(int(startTime))
 
-         endTime = CommonService.timestamp_to_str(int(endTime))
 
-         startYear, startMonth, startDay = \
 
-             str(startTime).split('-')[0], str(startTime).split('-')[1], str(startTime).split('-')[2]
 
-         # 结束时间
 
-         endYear, endMonth, endDay = str(endTime).split('-')[0], str(endTime).split('-')[1], str(endTime).split('-')[
 
-             2]
 
-         if unit == 'week' or unit == 'month':
 
-             startTime = parse('%s-%s-%s' % (startYear, startMonth, startDay))
 
-             endTime = parse('%s-%s-%s' % (endYear, endMonth, endDay))
 
-             time_list = CommonService.cutting_time(startTime, endTime, time_unit='day')
 
-         elif unit == 'year':
 
-             startYear, startMonth = int(startTime.split('-')[0]), int(startTime.split('-')[1])
 
-             endYear, endMonth = int(endTime.split('-')[0]), int(endTime.split('-')[1])
 
-             # 获取下个月的第一天
 
-             if startMonth == 12:
 
-                 startYear += 1
 
-                 startMonth = 1
 
-             else:
 
-                 startMonth += 1
 
-             #  计算(开始月,结束月)
 
-             startTime = parse('%s-%s-01 00:00:00' % (str(startYear), str(startMonth)))
 
-             # 获取上个月最后一天
 
-             if endMonth == 1:
 
-                 endYear -= 1
 
-                 endMonth = 12
 
-             else:
 
-                 endMonth -= 1
 
-             endDay = calendar.monthrange(endYear, endMonth)[1]
 
-             endTime = parse('%s-%s-%s 23:59:59' % (str(endYear), str(endMonth), endDay))
 
-             time_list = CommonService.cutting_time(startTime, endTime, time_unit='month')
 
-             #  开始月的时间区间
 
-             startMonth_time = CommonService.str_to_timestamp(str(startTime))
 
-             #  结束月的时间区间
 
-             endMonth_time = CommonService.str_to_timestamp(str(endTime))
 
-             diction['startMonth_time'] = startMonth_time
 
-             diction['endMonth_time'] = endMonth_time
 
-         diction['time_list'] = time_list
 
-         return diction
 
-     @staticmethod
 
-     def del_socket_schedule(request_dict, response, user_id):
 
-         """
 
-         批量刪除排程
 
-         @param request_dict: 请求参数
 
-         @param user_id: 用戶user_id
 
-         @request_dict ids: 排程id
 
-         @request_dict serialNumber: 设备序列号
 
-         @param response: 响应对象
 
-         @return: response
 
-         """
 
-         try:
 
-             with transaction.atomic():
 
-                 ids = request_dict.get('ids', None)
 
-                 serial_number = request_dict.get('serialNumber', None)
 
-                 if not all({ids, serial_number}):
 
-                     return response.json(444, {'error param': 'id or serialNumber'})
 
-                 device_info_qs = Device_Info.objects.filter(userID_id=user_id, serial_number=serial_number)
 
-                 if not device_info_qs.exists():
 
-                     return response.json(173)
 
-                 socket_schedule_qs = SocketSchedule.objects.filter(id__in=ids.split(','))
 
-                 if not socket_schedule_qs.exists():
 
-                     return response.json(173)
 
-                 # 发布MQTT消息通知设备删除排程任务
 
-                 # for val in socket_schedule_qs:
 
-                 #     if val.task_status:
 
-                 #         switch_status = 1 if val.switch_status else 0
 
-                 #         result = SmartSocketView.send_socket_schedule(val.serial_number, val.id, val.time_type,
 
-                 #                                                       val.start_time, val.end_time,
 
-                 #                                                       val.repeat, switch_status, 0)
 
-                 #         LOGGER.info('删除排程发布结果:{}'.format(result))
 
-                 socket_schedule_qs.delete()
 
-                 return response.json(0)
 
-         except Exception as e:
 
-             LOGGER.info('插座排程删除数据异常,errLine:{}, errMsg:{}'.format(e.__traceback__.tb_lineno, repr(e)))
 
-             return response.json(177)
 
-     @classmethod
 
-     def get_unit_scene(cls, request_dict, response):
 
-         """
 
-         查詢設備每日/月用電量
 
-         @request_dict serialNumber: 设备序列号
 
-         @request_dict startTime: 开始时间
 
-         @request_dict endTime: 结束时间
 
-         @param request_dict: 请求参数
 
-         @param response: 响应对象
 
-         @return: response
 
-         """
 
-         serial_number = request_dict.get('serialNumber', None)
 
-         unit = request_dict.get('unit', None)
 
-         startTime = request_dict.get('startTime', None)
 
-         endTime = request_dict.get('endTime', None)
 
-         if not all([unit, startTime, endTime, serial_number]):
 
-             return response.json(500, {'errno': 'unit or startTime or endTime or serialNumber'})
 
-         try:
 
-             socket_power_qs = SocketPowerStatistics.objects.filter(serial_number=serial_number). \
 
-                 values('electricity', 'accumulated_time', 'power', 'created_time')
 
-             if not socket_power_qs.exists():
 
-                 return response.json(0, {})
 
-             #  时间和功耗
 
-             data = {}
 
-             new_list = []
 
-             socket_qs = socket_power_qs.filter(created_time__gte=startTime, created_time__lt=endTime).aggregate(
 
-                 electricity=Sum('electricity'), accumulatedTime=Sum('accumulated_time'))
 
-             data['electricityTimeAll'] = round(socket_qs['electricity'], 2) if socket_qs[
 
-                 'electricity'] else 0
 
-             data['accumulatedTimeAll'] = socket_qs['accumulatedTime'] if socket_qs['accumulatedTime'] else 0
 
-             #  分割时间
 
-             diction = cls.splittings_time(startTime, endTime, unit)
 
-             if unit == 'year':
 
-                 # 开始月
 
-                 socket_qs = socket_power_qs.filter(created_time__gte=startTime,
 
-                                                    created_time__lt=diction['startMonth_time']).aggregate(
 
-                     electricity=Sum('electricity'), accumulatedTime=Sum('accumulated_time'))
 
-                 electricity = socket_qs['electricity'] if socket_qs[
 
-                     'electricity'] else 0
 
-                 # 標記月日
 
-                 subscript = cls.get_subscript(unit, startTime)
 
-                 new_list.append({
 
-                     'subscript': subscript,
 
-                     'time': int(startTime),
 
-                     'electricity': round(electricity, 2)
 
-                 })
 
-             # 查询天月
 
-             for item in diction['time_list']:
 
-                 socket_qs = socket_power_qs.filter(created_time__gte=item[0],
 
-                                                    created_time__lt=item[1]).aggregate(
 
-                     electricity=Sum('electricity'))
 
-                 electricity = socket_qs['electricity'] if socket_qs[
 
-                     'electricity'] else 0
 
-                 # 標記月日
 
-                 subscript = cls.get_subscript(unit, item[0])
 
-                 new_list.append({
 
-                     'subscript': subscript,
 
-                     'time': item[0],
 
-                     'electricity': round(electricity, 2)
 
-                 })
 
-             if unit == 'year':
 
-                 # 结束月
 
-                 socket_qs = socket_power_qs.filter(created_time__gte=diction['endMonth_time'],
 
-                                                    created_time__lt=endTime).aggregate(
 
-                     electricity=Sum('electricity'))
 
-                 electricity = socket_qs['electricity'] if socket_qs[
 
-                     'electricity'] else 0
 
-                 # 標記月日
 
-                 subscript = cls.get_subscript(unit, endTime)
 
-                 new_list.append({
 
-                     'subscript': subscript,
 
-                     'time': int(endTime),
 
-                     'electricity': round(electricity, 2)
 
-                 })
 
-             #  降序排序
 
-             # new_list.sort(key=lambda k: k["time"], reverse=True)
 
-             data['week_or_month_or_year'] = new_list
 
-             return response.json(0, data)
 
-         except Exception as e:
 
-             return response.json(500, 'error_line:{}, error_msg:{}'.format(e.__traceback__.tb_lineno, repr(e)))
 
-     @classmethod
 
-     def get_subscript(cls, unit, time_stamp):
 
-         """
 
-         標記月日
 
-         @param unit: 时间单位
 
-         @param time_stamp: 时间戳
 
-         @return: subscript
 
-         """
 
-         time_tuple = time.localtime(int(time_stamp))  # 把时间戳转换成时间元祖
 
-         time_tuple = time.strftime('%Y-%m-%d-%w', time_tuple)  # 把时间元祖转换成格式化好的时间
 
-         if unit == 'week' or unit == 'year':
 
-             if unit == 'week':
 
-                 subscript = int(str(time_tuple).split('-')[3])
 
-                 return subscript
 
-             else:
 
-                 Year, Month, Day = int(time_tuple.split('-')[0]), int(time_tuple.split('-')[1]), int(
 
-                     time_tuple.split('-')[2])
 
-                 subscript = datetime.date(Year, Month, Day).month
 
-                 subscript -= 1
 
-                 return subscript
 
-         else:
 
-             Year, Month, Day = int(time_tuple.split('-')[0]), int(time_tuple.split('-')[1]), int(
 
-                 time_tuple.split('-')[2])
 
-             subscript = datetime.date(Year, Month, Day).day
 
-             subscript -= 1
 
-             return subscript
 
-     @staticmethod
 
-     def get_schedule_data(request_dict, response):
 
-         """
 
-         查询插座日志记录日期
 
-         @request_dict serialNumber: 设备序列号
 
-         @param request_dict: 请求参数
 
-         @param response: 响应对象
 
-         @return: response
 
-         """
 
-         serial_number = request_dict.get('serialNumber', None)
 
-         if not serial_number:
 
-             return response.json(444, {'error': 'serialNumber'})
 
-         try:
 
-             socket_schedule_qs = SceneLog.objects.extra(
 
-                 select={'date': "FROM_UNIXTIME(created_time,'%%Y-%%m-%%d')"}).values('date').filter(
 
-                 device_id=serial_number).annotate(count=Count('created_time')).order_by('-date')[:31]
 
-             schedule_date_list = []
 
-             for socket_schedule in socket_schedule_qs:
 
-                 schedule_date_list.append({
 
-                     'timestamp': CommonService.str_to_timestamp(socket_schedule['date'], '%Y-%m-%d'),
 
-                     'count': socket_schedule['count'],
 
-                     'format': socket_schedule['date']
 
-                 })
 
-             return response.json(0, schedule_date_list)
 
-         except Exception as 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):
 
-         """
 
-         alexa智能开关
 
-         @request_dict serialNumber: 设备序列号
 
-         @request_dict status: 开关状态
 
-         @param request_dict: 请求参数
 
-         @param response: 响应对象
 
-         @return: response
 
-         """
 
-         serialNumber = request_dict.get('serial_number', None)
 
-         status = request_dict.get('power_controller', None)
 
-         if not all([serialNumber, status]):
 
-             return response.json(444)
 
-         # 同步数据库并下发MQTT消息到插座设备
 
-         try:
 
-             socket_info_qs = SocketInfo.objects.get(serial_number=serialNumber, type_switch=0)
 
-             device_id = socket_info_qs.device_id
 
-             result = cls.save_socket_switch(device_id, serialNumber, int(status))
 
-             if not result:
 
-                 return response.json(177)
 
-             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)))
 
-     @classmethod
 
-     def get_socket_state(cls, request_dict, response):
 
-         """
 
-         获取alexa智能开关状态
 
-         @request_dict serialNumber: 设备序列号
 
-         @request_dict status: 开关状态
 
-         @param request_dict: 请求参数
 
-         @param response: 响应对象
 
-         @return: response
 
-         """
 
-         serial_number = request_dict.get('serial_number', None)
 
-         if not all([serial_number]):
 
-             return response.json(444)
 
-         # 同步数据库并下发MQTT消息到插座设备
 
-         try:
 
-             socket_info_qs = SocketInfo.objects.filter(serial_number=serial_number).values('status')
 
-             if socket_info_qs.exists():
 
-                 res = {
 
-                     'power_state': socket_info_qs[0]['status']
 
-                 }
 
-                 return response.json(0, res)
 
-             return response.json(173)
 
-         except Exception as e:
 
-             print(e)
 
-             return response.json(500, 'error_line:{}, error_msg:{}'.format(e.__traceback__.tb_lineno, repr(e)))
 
-     @classmethod
 
-     def delete_alexa_socket(cls, serial_number):
 
-         url = 'https://www.zositech.xyz/deviceStatus/deleteSwitch'
 
-         data = {
 
-             'serial_number': serial_number
 
-         }
 
-         try:
 
-             requests.post(url=url, data=data, timeout=5)
 
-         except Exception as e:
 
-             print(repr(e))
 
-     @classmethod
 
-     def socket_msg_push(cls, request_dict, response):
 
-         """
 
-         智能插座开关状态推送
 
-         """
 
-         try:
 
-             serial_number = request_dict.get('serialNumber', None)
 
-             device_time = request_dict.get('deviceTime', None)
 
-             status = request_dict.get('status', None)
 
-             if not all([serial_number, status, device_time]):
 
-                 return response.json(444)
 
-             status = int(status)
 
-             now_time = int(device_time) if device_time else int(time.time())
 
-             # 获取主用户设备id
 
-             log_dict = {
 
-                 'status': status,
 
-                 'device_id': serial_number,
 
-                 'created_time': now_time,
 
-             }
 
-             SceneLog.objects.create(**log_dict)
 
-             LOGGER.info('成功接收并保存,插座序列号{},状态:{}'.format(serial_number, status))
 
-             return response.json(0)
 
-         except Exception as e:
 
-             print(repr(e))
 
-             LOGGER.info('---插座开关日志推送接口异常--- {}'.format(repr(e)))
 
-             return response.json(500, repr(e))
 
 
  |