# -*- encoding: utf-8 -*- """ @File : DeviceReportController.py @Time : 2025/4/8 16:33 @Author : stephen @Email : zhangdongming@asj6.wecom.work @Software: PyCharm """ import logging from datetime import datetime, timezone from django.http import JsonResponse from django.views import View from django.core.exceptions import ValidationError from Model.models import DeviceDailyReport from Service.DevicePushService import DevicePushService TIME_LOGGER = logging.getLogger('time') ERROR_INFO_LOGGER = logging.getLogger('error_info') class DeviceReportView(View): def post(self, request, *args, **kwargs): operation = kwargs.get('operation') if operation == 'batteryLevel': return self.handle_battery_report(request.POST) return JsonResponse( {'code': 404, 'msg': 'Operation not found'}, status=404 ) def handle_battery_report(self, data): try: # 验证并解码设备令牌 etk = data.get('etk') TIME_LOGGER.info(f'设备电池报告参数:{data}') if not etk: raise ValidationError('Missing etk parameter') uid = DevicePushService.decode_uid(etk, None) if len(uid) not in (14, 20): raise ValidationError('Invalid device UID format') # 参数提取和类型转换 wake_sleep = self.parse_int_param(data, 'pirWakeupCount') + self.parse_int_param(data, 'mqttWakeupCount') report_params = { 'human_detection': self.parse_int_param(data, 'humanDetection'), 'pir_wakeup_count': self.parse_int_param(data, 'pirWakeupCount'), 'mqtt_wakeup_count': self.parse_int_param(data, 'mqttWakeupCount'), 'wake_sleep': wake_sleep, 'working_hours': self.parse_int_param(data, 'workingHours'), 'battery_level': self.parse_int_param(data, 'batteryLevel'), 'report_time': self.parse_int_param(data, 'reportTime'), } # 时间戳验证 report_date = datetime.fromtimestamp(report_params['report_time'], tz=timezone.utc) # 数据库操作 DeviceDailyReport.objects.create( device_id=uid, type=1, report_date=report_date, **report_params ) TIME_LOGGER.info(f'设备保存电池报告uid: {uid}') return JsonResponse({'code': 0, 'msg': 'Report saved successfully'}) except ValidationError as e: ERROR_INFO_LOGGER.warning(f'Validation error: {e.message}', exc_info=True) return JsonResponse({'code': 400, 'msg': e.message}, status=400) except Exception as e: ERROR_INFO_LOGGER.error(f'Unexpected error: {str(e)}', exc_info=True) return JsonResponse( {'code': 500, 'msg': 'Internal server error'}, status=500 ) @classmethod def parse_int_param(cls, data, param_name): """辅助方法:安全提取并转换整型参数""" value = data.get(param_name) if not value: raise ValidationError(f'Missing {param_name} parameter') try: return int(value) except ValueError: raise ValidationError(f'Invalid {param_name} format')