DeviceReportController.py 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990
  1. # -*- encoding: utf-8 -*-
  2. """
  3. @File : DeviceReportController.py
  4. @Time : 2025/4/8 16:33
  5. @Author : stephen
  6. @Email : zhangdongming@asj6.wecom.work
  7. @Software: PyCharm
  8. """
  9. import logging
  10. from datetime import datetime, timezone
  11. from django.http import JsonResponse
  12. from django.views import View
  13. from django.core.exceptions import ValidationError
  14. from Model.models import DeviceDailyReport
  15. from Service.DevicePushService import DevicePushService
  16. TIME_LOGGER = logging.getLogger('time')
  17. ERROR_INFO_LOGGER = logging.getLogger('error_info')
  18. class DeviceReportView(View):
  19. def post(self, request, *args, **kwargs):
  20. operation = kwargs.get('operation')
  21. if operation == 'batteryLevel':
  22. return self.handle_battery_report(request.POST)
  23. return JsonResponse(
  24. {'code': 404, 'msg': 'Operation not found'},
  25. status=404
  26. )
  27. def handle_battery_report(self, data):
  28. try:
  29. # 验证并解码设备令牌
  30. etk = data.get('etk')
  31. TIME_LOGGER.info(f'设备电池报告参数:{data}')
  32. if not etk:
  33. raise ValidationError('Missing etk parameter')
  34. uid = DevicePushService.decode_uid(etk, None)
  35. if len(uid) not in (14, 20):
  36. raise ValidationError('Invalid device UID format')
  37. # 参数提取和类型转换
  38. wake_sleep = self.parse_int_param(data, 'pirWakeupCount') + self.parse_int_param(data, 'mqttWakeupCount')
  39. report_params = {
  40. 'human_detection': self.parse_int_param(data, 'humanDetection'),
  41. 'pir_wakeup_count': self.parse_int_param(data, 'pirWakeupCount'),
  42. 'mqtt_wakeup_count': self.parse_int_param(data, 'mqttWakeupCount'),
  43. 'wake_sleep': wake_sleep,
  44. 'working_hours': self.parse_int_param(data, 'workingHours'),
  45. 'battery_level': self.parse_int_param(data, 'batteryLevel'),
  46. 'report_time': self.parse_int_param(data, 'reportTime'),
  47. }
  48. # 时间戳验证
  49. report_date = datetime.fromtimestamp(report_params['report_time'], tz=timezone.utc)
  50. # 数据库操作
  51. DeviceDailyReport.objects.create(
  52. device_id=uid,
  53. type=1,
  54. report_date=report_date,
  55. **report_params
  56. )
  57. TIME_LOGGER.info(f'设备保存电池报告uid: {uid}')
  58. return JsonResponse({'code': 0, 'msg': 'Report saved successfully'})
  59. except ValidationError as e:
  60. ERROR_INFO_LOGGER.warning(f'Validation error: {e.message}', exc_info=True)
  61. return JsonResponse({'code': 400, 'msg': e.message}, status=400)
  62. except Exception as e:
  63. ERROR_INFO_LOGGER.error(f'Unexpected error: {str(e)}', exc_info=True)
  64. return JsonResponse(
  65. {'code': 500, 'msg': 'Internal server error'},
  66. status=500
  67. )
  68. @classmethod
  69. def parse_int_param(cls, data, param_name):
  70. """辅助方法:安全提取并转换整型参数"""
  71. value = data.get(param_name)
  72. if not value:
  73. raise ValidationError(f'Missing {param_name} parameter')
  74. try:
  75. return int(value)
  76. except ValueError:
  77. raise ValidationError(f'Invalid {param_name} format')