|
@@ -0,0 +1,94 @@
|
|
|
+# -*- encoding: utf-8 -*-
|
|
|
+"""
|
|
|
+@File : DeviceReportController.py
|
|
|
+@Time : 2025/4/8 16:33
|
|
|
+@Author : stephen
|
|
|
+@Email : zhangdongming@asj6.wecom.work
|
|
|
+@Software: PyCharm
|
|
|
+"""
|
|
|
+import logging
|
|
|
+import time
|
|
|
+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') - 10800,
|
|
|
+ }
|
|
|
+
|
|
|
+ # 时间戳验证
|
|
|
+ report_date = datetime.fromtimestamp(report_params['report_time'], tz=timezone.utc)
|
|
|
+
|
|
|
+ # 数据库操作
|
|
|
+ n_time = int(time.time())
|
|
|
+ DeviceDailyReport.objects.create(
|
|
|
+ device_id=uid,
|
|
|
+ type=1,
|
|
|
+ report_date=report_date,
|
|
|
+ **report_params,
|
|
|
+ created_time=n_time,
|
|
|
+ updated_time=n_time
|
|
|
+ )
|
|
|
+
|
|
|
+ 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')
|