DeviceManagementController.py 118 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493
  1. #!/usr/bin/env python3
  2. # -*- coding: utf-8 -*-
  3. import datetime
  4. import io
  5. import json
  6. import operator
  7. import os
  8. import threading
  9. import time
  10. import csv
  11. import oss2
  12. import requests
  13. from obs import ObsClient
  14. from django.core.paginator import Paginator
  15. from django.db import transaction
  16. from django.db.models import Q, F, Sum, OuterRef, Min, Subquery
  17. from django.forms.models import model_to_dict
  18. from django.utils import timezone
  19. from django.views.generic.base import View
  20. from Ansjer.config import LOGGER, SERIAL_DOMAIN_NAME, HUAWEICLOUD_AK, HUAWEICLOUD_SK, HUAWEICLOUD_OBS_SERVER, \
  21. HUAWEICLOUD_BAIDU_BIG_MODEL_LICENSE_BUKET,CONFIG_INFO, CONFIG_TEST, CONFIG_CN, CONFIG_US, CONFIG_EUR
  22. from Ansjer.config import OSS_STS_ACCESS_KEY, OSS_STS_ACCESS_SECRET, AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, \
  23. AWS_SES_ACCESS_REGION
  24. from Ansjer.config import SERVER_DOMAIN_TEST, SERVER_DOMAIN_CN, SERVER_DOMAIN_US, SERVER_DOMAIN_EUR
  25. from Model.models import Device_Info, UidSetModel, LogModel, UID_Bucket, Unused_Uid_Meal, StsCrdModel, \
  26. VodHlsModel, ExperienceContextModel, DeviceTypeModel, UidUserModel, ExperienceAiModel, AiService, \
  27. AppBundle, App_Info, AppDeviceType, DeviceNameLanguage, UIDCompanySerialModel, UidPushModel, \
  28. CustomCustomerOrderInfo, CustomCustomerDevice, DeviceVersionInfo, VoicePromptModel, DeviceAlgorithmExplain, BaiduBigModelLicense, \
  29. DeviceDailyReport, Instavision
  30. from Object.AWS.AmazonS3Util import AmazonS3Util
  31. from Object.Enums.RedisKeyConstant import RedisKeyConstant
  32. from Object.RedisObject import RedisObject
  33. from Object.ResponseObject import ResponseObject
  34. from Object.TokenObject import TokenObject
  35. from Service.CommonService import CommonService
  36. from Service.EquipmentInfoService import EquipmentInfoService
  37. from Service.ModelService import ModelService
  38. from Service.VodHlsService import SplitVodHlsObject
  39. class DeviceManagement(View):
  40. def get(self, request, *args, **kwargs):
  41. request.encoding = 'utf-8'
  42. operation = kwargs.get('operation')
  43. return self.validation(request.GET, request, operation)
  44. def post(self, request, *args, **kwargs):
  45. request.encoding = 'utf-8'
  46. operation = kwargs.get('operation')
  47. return self.validation(request.POST, request, operation)
  48. def validation(self, request_dict, request, operation):
  49. language = request_dict.get('language', 'en')
  50. response = ResponseObject(language, 'pc')
  51. if operation == 'addDeviceType':
  52. return self.addDeviceType(request, request_dict, response)
  53. elif operation == 'delDeviceData': # 删除设备数据
  54. return self.del_device_data(request, request_dict, response)
  55. elif operation == 'getDeviceIcon': # app获取设备图标
  56. response = ResponseObject(language)
  57. return self.get_device_icon(request_dict, response)
  58. elif operation == 'addAppDeviceType': # 添加app设备类型数据并上传图标
  59. return self.add_app_device_type(request_dict, response, request)
  60. elif operation == 'getUidPush': # 查询推送信息
  61. return self.get_uid_push(request_dict, response)
  62. elif operation == 'checkDeviceInfo':
  63. return self.query_device_user(request, request_dict, response)
  64. else:
  65. tko = TokenObject(
  66. request.META.get('HTTP_AUTHORIZATION'),
  67. returntpye='pc')
  68. if tko.code != 0:
  69. return response.json(tko.code)
  70. response.lang = tko.lang
  71. userID = tko.userID
  72. if not userID:
  73. return response.json(444, 'userID')
  74. if operation == 'getDeviceInfoList': # 获取设备信息数据
  75. return self.get_device_info_list(request_dict, response)
  76. elif operation == 'deleteDevice': # 删除设备
  77. return self.deleteDevice(request, request_dict, response, userID)
  78. elif operation == 'delDeviceDataV2': # 后台设备删除数据
  79. return self.del_device_data(request, request_dict, response, userID)
  80. elif operation == 'resetVod': # 重置云存
  81. return self.resetVod(request, request_dict, response)
  82. elif operation == 'resetAi': # 重置AI
  83. return self.reset_ai(request, request_dict, response)
  84. elif operation == 'resetPrimaryUser':
  85. return self.resetPrimaryUser(request, request_dict, response)
  86. elif operation == 'getDeviceType':
  87. return self.getDeviceType(response)
  88. elif operation == 'getDeviceTypeList':
  89. return self.getDeviceTypeList(request_dict, response)
  90. elif operation == 'deleteDeviceType':
  91. return self.deleteDeviceType(request_dict, response)
  92. elif operation == 'getAppDeviceTypeList': # 获取app设备类型数据
  93. return self.get_app_device_type_list(request_dict, response)
  94. elif operation == 'getAppBundleIdList': # 获取app包id数据
  95. return self.get_app_bundle_id_list(response)
  96. elif operation == 'editAppDeviceType': # 编辑app设备类型数据
  97. return self.edit_app_device_type(request_dict, request, response)
  98. elif operation == 'batchEditAppDeviceType': # 批量编辑app设备类型数据
  99. return self.batch_edit_app_device_type(request_dict, request, response)
  100. elif operation == 'deleteAppDeviceType': # 删除app设备类型数据
  101. return self.delete_app_device_type(request_dict, response)
  102. elif operation == 'getAppBundle': # 获取app版本包
  103. return self.get_app_bundle(response)
  104. elif operation == 'resetAll': # 重置设备主用户/云存/AI
  105. return self.reset_all(request, request_dict, response)
  106. elif operation == 'getAppNameList': # 获取app版本包
  107. return self.get_app_name_list(response)
  108. elif operation == 'callAddAppDeviceType': # 可选服添加app设备类型数据并上传图标
  109. return self.call_add_app_device_type(request_dict, response, request)
  110. elif operation == 'getCustomerDeviceList': # 查询扫码添加设备列表
  111. return self.get_customer_device_list(request_dict, response)
  112. # 设备型号版本
  113. elif operation == 'getDeviceVerInfo': # 查询设备型号版本列表
  114. return self.get_device_ver_info(request_dict, response)
  115. elif operation == 'addDeviceVerInfo': # 添加设备型号版本
  116. return self.add_device_ver_info(request_dict, response)
  117. elif operation == 'editDeviceVerInfo': # 编辑设备型号版本
  118. return self.edit_device_ver_info(request_dict, response)
  119. elif operation == 'delDeviceVerInfo': # 删除设备型号版本
  120. return self.del_device_ver_info(request_dict, response)
  121. elif operation == 'syncDeviceVersion': # 一键同步
  122. return self.sync_device_version(request_dict, response)
  123. # 设备语音设置
  124. elif operation == 'getDeviceVoice': # 获取设备音频
  125. return self.get_device_voice(request_dict, response)
  126. elif operation == 'algorithmTypeList': # 添加设备型号版本
  127. return self.algorithm_type_list(response)
  128. elif operation == 'addDeviceVoice': # 获取设备音频列表
  129. return self.add_device_voice(request, request_dict, response)
  130. elif operation == 'editDeviceVoice':
  131. return self.edit_device_voice(request_dict, response)
  132. elif operation == 'delDeviceVoice':
  133. return self.del_device_voice(request_dict, response)
  134. elif operation == 'deviceTypeList':
  135. return self.device_type_list(response)
  136. # 百度大模型
  137. elif operation == 'getBaiduBigModelLicense': # 查询大模型许可证
  138. return self.get_baidu_big_model_license(request_dict, response)
  139. elif operation == 'addBaiduBigModelLicense': # 添加大模型许可证
  140. return self.add_baidu_big_model_license(request, response)
  141. elif operation == 'editBaiduBigModelLicense': # 编辑大模型许可证
  142. return self.edit_baidu_big_model_license(request, request_dict, response)
  143. elif operation == 'delBaiduBigModelLicense': # 删除大模型许可证
  144. return self.del_baidu_big_model_license(request_dict, response)
  145. # Instavision即时视觉
  146. elif operation == 'getInstavision': # 查询即时视觉列表
  147. return self.get_instavision(request_dict, response)
  148. elif operation == 'addInstavision': # 添加即时视觉
  149. return self.add_instavision(request, response)
  150. elif operation == 'editInstavision': # 编辑即时视觉
  151. return self.edit_instavision(request_dict, response)
  152. elif operation == 'delInstavision': # 删除即时视觉
  153. return self.del_instavision(request_dict, response)
  154. elif operation == 'devicePowerDisplay':
  155. return self.device_power_display(request_dict, response)
  156. else:
  157. return response.json(444, 'operation')
  158. @classmethod
  159. def get_app_bundle(cls, response):
  160. """
  161. 获取app版本id
  162. """
  163. app_bundle_qs = AppBundle.objects.all().values('id', 'app_bundle_id')
  164. if not app_bundle_qs.exists():
  165. return response.json(0)
  166. app_bundle_list = []
  167. for app_bundle in app_bundle_qs:
  168. app_bundle_qs.exists()
  169. app_bundle_list.append(app_bundle)
  170. return response.json(0, app_bundle_list)
  171. @classmethod
  172. def get_device_info_list(cls, request_dict, response):
  173. pageNo = request_dict.get('pageNo', None)
  174. pageSize = request_dict.get('pageSize', None)
  175. UID = request_dict.get('UID', None)
  176. serialNumber = request_dict.get('serialNumber', None)
  177. NickName = request_dict.get('NickName', None)
  178. username = request_dict.get('username', None)
  179. version = request_dict.get('version', None)
  180. Type = request_dict.get('Type', None)
  181. if not all([pageNo, pageSize]):
  182. return response.json(444)
  183. page = int(pageNo)
  184. line = int(pageSize)
  185. try:
  186. if any([UID, serialNumber, NickName, username, version, Type]): # 条件查询
  187. if UID:
  188. device_info_qs = Device_Info.objects.filter(UID__icontains=UID)
  189. if serialNumber:
  190. device_info_qs = Device_Info.objects.filter(serial_number__icontains=serialNumber[:9])
  191. if NickName:
  192. device_info_qs = Device_Info.objects.filter(NickName__icontains=NickName)
  193. if username:
  194. device_info_qs = Device_Info.objects.filter(Q(userID__username__icontains=username) |
  195. Q(userID__userEmail__icontains=username) |
  196. Q(userID__phone__icontains=username))
  197. if version:
  198. uid_list = UidSetModel.objects.filter(version__icontains=version).values_list('uid', flat=True)
  199. device_info_qs = Device_Info.objects.filter(UID__in=uid_list)
  200. if Type:
  201. type_list = DeviceTypeModel.objects.filter(name=Type).values_list('type', flat=True)
  202. device_info_qs = Device_Info.objects.filter(Type__in=type_list)
  203. total = device_info_qs.count()
  204. if not total:
  205. return response.json(0, {'list': {}, 'total': 0})
  206. device_info_qs = device_info_qs[(page - 1) * line:page * line]
  207. else: # 查询全部
  208. total = Device_Info.objects.filter().count()
  209. device_info_qs = Device_Info.objects.filter()[(page - 1) * line:page * line]
  210. if not device_info_qs.exists():
  211. return response.json(0, {'list': {}, 'total': 0})
  212. device_info_list = CommonService.qs_to_dict(device_info_qs)
  213. for k, v in enumerate(device_info_list["datas"]):
  214. for device_info in device_info_qs:
  215. if v['pk'] == device_info.id:
  216. # 设备的用户名和主用户
  217. username = ModelService.get_user_name(device_info_list["datas"][k]['fields']['userID'])
  218. device_info_list["datas"][k]['fields']['username'] = username
  219. device_info_list["datas"][k]['fields']['vodPrimaryMaster'] = \
  220. device_info_list["datas"][k]['fields']['vodPrimaryMaster']
  221. # 设备类型,是否支持Alexa和ip
  222. type = device_info_list["datas"][k]['fields']['Type']
  223. device_type_qs = DeviceTypeModel.objects.filter(type=type).values('name')
  224. if device_type_qs.exists():
  225. device_info_list["datas"][k]['fields']['Type'] = device_type_qs[0]['name']
  226. uid_set_qs = UidSetModel.objects.filter(
  227. uid=device_info_list["datas"][k]['fields']['UID']). \
  228. values('detect_status', 'is_alexa', 'ip', 'version', 'is_ai', 'is_human', 'cloud_vod',
  229. 'ucode', 'device_type')
  230. if uid_set_qs.exists():
  231. # 移动侦测
  232. iSNotification = '开' if uid_set_qs[0]['detect_status'] else '关'
  233. device_info_list["datas"][k]['fields']['iSNotification'] = iSNotification
  234. isAlexa = '是' if uid_set_qs[0]['is_alexa'] else '否'
  235. isHuman = '是' if uid_set_qs[0]['is_human'] else '否'
  236. cloud_vod = CommonService.is_cloud_device(uid_set_qs[0]['ucode'],
  237. uid_set_qs[0]['device_type'])
  238. if cloud_vod:
  239. cloud_vod = '支持'
  240. else:
  241. cloud_vod = '不支持'
  242. if uid_set_qs[0]['is_ai'] == 2:
  243. isAI = '不支持'
  244. else:
  245. isAI = '支持'
  246. device_info_list["datas"][k]['fields']['isHuman'] = isHuman
  247. device_info_list["datas"][k]['fields']['isAI'] = isAI
  248. device_info_list["datas"][k]['fields']['isAlexa'] = isAlexa
  249. device_info_list["datas"][k]['fields']['cloudVod'] = cloud_vod
  250. device_info_list["datas"][k]['fields']['ip'] = uid_set_qs[0]['ip']
  251. device_info_list["datas"][k]['fields']['version'] = uid_set_qs[0]['version']
  252. uid_bucket_qs = UID_Bucket.objects.filter(
  253. uid=device_info_list["datas"][k]['fields']['UID']).values('status')
  254. # 0是关闭,1是开启
  255. if uid_bucket_qs.exists():
  256. res = []
  257. for uid_bucket in uid_bucket_qs:
  258. status = uid_bucket['status']
  259. res.append(status)
  260. if 1 in res:
  261. device_info_list["datas"][k]['fields']['status'] = 1
  262. else:
  263. device_info_list["datas"][k]['fields']['status'] = 0
  264. else:
  265. device_info_list["datas"][k]['fields']['status'] = 0
  266. # AI开关状态
  267. ai_service = AiService.objects.filter(uid=device_info_list["datas"][k]['fields']['UID']).values(
  268. 'detect_status')
  269. if ai_service.exists():
  270. if ai_service[0]['detect_status']:
  271. device_info_list["datas"][k]['fields']['ai_status'] = 1
  272. else:
  273. device_info_list["datas"][k]['fields']['ai_status'] = 0
  274. else:
  275. device_info_list["datas"][k]['fields']['ai_status'] = 0
  276. # 时间格式化修改
  277. device_info_list["datas"][k]['fields']['update_time'] = device_info_list["datas"][k]['fields']['update_time'].split('.')[0].replace('T', ' ')
  278. device_info_list["datas"][k]['fields']['data_joined'] = device_info_list["datas"][k]['fields']['data_joined'].split('.')[0].replace('T', ' ')
  279. return response.json(0, {'list': device_info_list, 'total': total})
  280. except Exception as e:
  281. print(e)
  282. return response.json(500, 'error_line:{}, error_msg:{}'.format(e.__traceback__.tb_lineno, repr(e)))
  283. # 根据id删除设备
  284. def deleteDevice(self, request, request_dict, response, user_id):
  285. deviceID = request_dict.get('deviceID', None)
  286. userID = request_dict.get('userID', None)
  287. uid = request_dict.get('uid', None)
  288. if not all([deviceID, userID, uid]):
  289. return response.json(444)
  290. try:
  291. redis = RedisObject(3)
  292. with transaction.atomic():
  293. Device_Info.objects.filter(id=deviceID).delete()
  294. UidPushModel.objects.filter(uid_set__uid=uid).delete()
  295. # 删除推送消息
  296. EquipmentInfoService.delete_all_equipment_info(device_user_id=userID, device_uid=uid)
  297. # 构建Redis键
  298. device_key = f"{RedisKeyConstant.BASIC_USER.value}{userID}:UID:{uid}"
  299. redis.del_data(device_key)
  300. content = json.loads(json.dumps(request_dict))
  301. ip = CommonService.get_ip_address(request)
  302. log = {
  303. 'user_id': 2,
  304. 'status': 200,
  305. 'time': int(time.time()),
  306. 'url': 'deviceManagement/deleteDevice',
  307. 'content': user_id,
  308. 'ip': ip,
  309. 'operation': '删除设备和配置记录:{}'.format(json.dumps(content)),
  310. }
  311. LogModel.objects.create(**log)
  312. return response.json(0)
  313. except Exception as e:
  314. print(e)
  315. return response.json(500, 'error_line:{}, error_msg:{}'.format(e.__traceback__.tb_lineno, repr(e)))
  316. # 重置设备主用户
  317. def resetPrimaryUser(self, request, request_dict, response):
  318. uid = request_dict.get('uid', None)
  319. if not uid:
  320. return response.json(404)
  321. try:
  322. # 记录操作日志
  323. ip = CommonService.get_ip_address(request)
  324. content = json.loads(json.dumps(request_dict))
  325. log = {
  326. 'ip': ip,
  327. 'user_id': 2,
  328. 'status': 200,
  329. 'time': int(time.time()),
  330. 'url': 'deviceManagement/resetPrimaryUser',
  331. 'content': json.dumps(content),
  332. 'operation': '{}重置设备主用户'.format(uid),
  333. }
  334. LogModel.objects.create(**log)
  335. Device_Info.objects.filter(UID=uid).update(vodPrimaryUserID='', vodPrimaryMaster='')
  336. return response.json(0)
  337. except Exception as e:
  338. return response.json(500, 'error_line:{}, error_msg:{}'.format(e.__traceback__.tb_lineno, repr(e)))
  339. # 重置设备云存
  340. def resetVod(self, request, request_dict, response):
  341. uid = request_dict.get('uid', None)
  342. if not uid:
  343. return response.json(444)
  344. try:
  345. # 记录操作日志
  346. ip = CommonService.get_ip_address(request)
  347. content = json.loads(json.dumps(request_dict))
  348. log = {
  349. 'ip': ip,
  350. 'user_id': 2,
  351. 'status': 200,
  352. 'time': int(time.time()),
  353. 'url': 'deviceManagement/resetVod',
  354. 'content': json.dumps(content),
  355. 'operation': '{}重置云存'.format(uid),
  356. }
  357. with transaction.atomic():
  358. LogModel.objects.create(**log)
  359. # 删除和更新设备云存相关数据
  360. UID_Bucket.objects.filter(uid=uid).delete()
  361. AiService.objects.filter(uid=uid).delete()
  362. Unused_Uid_Meal.objects.filter(uid=uid).delete()
  363. # Order_Model.objects.filter(UID=uid, order_type=0).delete()
  364. StsCrdModel.objects.filter(uid=uid).delete()
  365. VodHlsModel.objects.filter(uid=uid).delete()
  366. # 删除vod_hls分表数据
  367. split_vod_hls_obj = SplitVodHlsObject()
  368. split_vod_hls_obj.del_vod_hls_data(uid=uid)
  369. ExperienceContextModel.objects.filter(uid=uid).delete()
  370. Device_Info.objects.filter(UID=uid).update(vodPrimaryUserID='', vodPrimaryMaster='')
  371. return response.json(0)
  372. except Exception as e:
  373. print(e)
  374. return response.json(500, 'error_line:{}, error_msg:{}'.format(e.__traceback__.tb_lineno, repr(e)))
  375. @staticmethod
  376. def reset_ai(request, request_dict, response):
  377. uid = request_dict.get('uid', None)
  378. if not uid:
  379. return response.json(444)
  380. try:
  381. # 记录操作日志
  382. ip = CommonService.get_ip_address(request)
  383. content = json.loads(json.dumps(request_dict))
  384. log = {
  385. 'ip': ip,
  386. 'user_id': 2,
  387. 'status': 200,
  388. 'time': int(time.time()),
  389. 'url': 'deviceManagement/resetAi',
  390. 'content': json.dumps(content),
  391. 'operation': '{}重置AI'.format(uid),
  392. }
  393. with transaction.atomic():
  394. LogModel.objects.create(**log)
  395. # 删除和更新设备AI相关数据
  396. ExperienceAiModel.objects.filter(uid=uid).delete()
  397. AiService.objects.filter(uid=uid).delete()
  398. return response.json(0)
  399. except Exception as e:
  400. print(e)
  401. return response.json(500, 'error_line:{}, error_msg:{}'.format(e.__traceback__.tb_lineno, repr(e)))
  402. @staticmethod
  403. def getDeviceType(response):
  404. try:
  405. device_type_qs = DeviceTypeModel.objects.all().values('type', 'name')
  406. print(list(device_type_qs))
  407. return response.json(0, {'list': list(device_type_qs)})
  408. except Exception as e:
  409. return response.json(500, 'error_line:{}, error_msg:{}'.format(e.__traceback__.tb_lineno, repr(e)))
  410. # 获取设备类型数据
  411. def getDeviceTypeList(self, request_dict, response):
  412. name = request_dict.get('name', None)
  413. pageNo = request_dict.get('pageNo', None)
  414. pageSize = request_dict.get('pageSize', None)
  415. if not all([pageNo, pageSize]):
  416. return response.json(444)
  417. page = int(pageNo)
  418. line = int(pageSize)
  419. try:
  420. if name:
  421. device_type_qs = DeviceTypeModel.objects.filter(name__contains=name).values()
  422. total = len(device_type_qs)
  423. else:
  424. device_type_qs = DeviceTypeModel.objects.filter().values()[(page - 1) * line:page * line]
  425. total = DeviceTypeModel.objects.filter().count()
  426. if not device_type_qs.exists():
  427. return response.json(173)
  428. device_type_list = []
  429. for device_type in device_type_qs:
  430. auth = oss2.Auth(OSS_STS_ACCESS_KEY, OSS_STS_ACCESS_SECRET)
  431. bucket = oss2.Bucket(auth, 'oss-cn-shenzhen.aliyuncs.com', 'ansjer-static-resources')
  432. icon = device_type['icon']
  433. url = 'device_type/' + icon
  434. device_type['icon'] = bucket.sign_url('GET', url, 3600)
  435. device_type_list.append(device_type)
  436. return response.json(0, {'list': device_type_list, 'total': total})
  437. except Exception as e:
  438. print(e)
  439. return response.json(500, 'error_line:{}, error_msg:{}'.format(e.__traceback__.tb_lineno, repr(e)))
  440. # 删除设备类型
  441. def deleteDeviceType(self, request_dict, response):
  442. deviceTypeID = request_dict.get('deviceTypeID', None)
  443. if not deviceTypeID:
  444. return response.json(444)
  445. try:
  446. DeviceTypeModel.objects.filter(id=deviceTypeID).delete()
  447. return response.json(0)
  448. except Exception as e:
  449. print(e)
  450. return response.json(500, 'error_line:{}, error_msg:{}'.format(e.__traceback__.tb_lineno, repr(e)))
  451. # 添加设备类型
  452. def addDeviceType(self, request, request_dict, response):
  453. iconFile = request.FILES.get('iconFile', None)
  454. name = request_dict.get('name', None)
  455. model = request_dict.get('model', None)
  456. type = request_dict.get('type', None)
  457. ptz_type = request_dict.get('ptz_type', None)
  458. if not all([iconFile, name, model, type, ptz_type]):
  459. return response.json(444)
  460. try:
  461. model = int(model)
  462. ptz_type = int(ptz_type)
  463. icon = iconFile.name
  464. now_time = int(time.time())
  465. # 上传文件到阿里云OSS
  466. auth = oss2.Auth(OSS_STS_ACCESS_KEY, OSS_STS_ACCESS_SECRET)
  467. bucket = oss2.Bucket(auth, 'oss-cn-shenzhen.aliyuncs.com', 'ansjer-static-resources')
  468. key = 'device_type/' + icon # 图片文件存放于 device_type 目录下
  469. # https://oss.console.aliyun.com/bucket/oss-cn-shenzhen/ansjer-static-resources/object?path=device_type%2F
  470. bucket.put_object(key=key, data=iconFile)
  471. DeviceTypeModel.objects.create(name=name, model=model, type=type, ptz_type=ptz_type, icon=icon,
  472. add_time=now_time, update_time=now_time)
  473. return response.json(0)
  474. except Exception as e:
  475. print(e)
  476. return response.json(500, 'error_line:{}, error_msg:{}'.format(e.__traceback__.tb_lineno, repr(e)))
  477. @staticmethod
  478. def del_device_data(request, request_dict, response, user_id=''):
  479. uidList = request_dict.get('uidList', None)
  480. delDataOptions = request_dict.get('delDataOptions', None)
  481. serialNumberList = request_dict.get('serialNumberList', None)
  482. if not all([uidList or serialNumberList, delDataOptions]):
  483. return response.json(444)
  484. # 记录日志
  485. content = json.loads(json.dumps(request_dict))
  486. ip = CommonService.get_ip_address(request)
  487. log = {
  488. 'user_id': 2,
  489. 'status': 200,
  490. 'time': int(time.time()),
  491. 'url': 'deviceManagement/delDeviceData',
  492. 'content': delDataOptions,
  493. 'ip': ip,
  494. 'operation': '上传文件设备重置删除前:user:{},{}'.format(user_id, json.dumps(content)),
  495. }
  496. LogModel.objects.create(**log)
  497. try:
  498. with transaction.atomic():
  499. if uidList:
  500. # uid
  501. uidList = uidList.splitlines() # 按行('\r', '\r\n', \n')切割字符串返回列表
  502. uid_list = []
  503. for uid in uidList:
  504. uid_val = uid.replace(" ", "")
  505. if not uid_val:
  506. continue
  507. uid_list.append(uid_val)
  508. uidList = uid_list
  509. else:
  510. # 序列号
  511. serialNumberList = serialNumberList.splitlines() # 按行('\r', '\r\n', \n')切割字符串返回列表
  512. serial_number_list = []
  513. for serial_number in serialNumberList:
  514. serial_number = serial_number.replace(" ", "")
  515. if not serial_number:
  516. continue
  517. serial_number_list.append(serial_number[0:6])
  518. uid_company_serial_qs = UIDCompanySerialModel.objects.filter(
  519. company_serial__serial_number__in=serial_number_list).values('uid__uid')
  520. uidList = [item[key] for item in uid_company_serial_qs for key in item]
  521. # 根据删除项删除相关数据
  522. if '设备信息数据' in delDataOptions:
  523. # 删除用户UID缓存
  524. user_list = list(Device_Info.objects.filter(UID__in=uidList).values('userID_id', 'UID'))
  525. thread = threading.Thread(target=DeviceManagement.deleteDeviceCache, args=(user_list,))
  526. thread.start()
  527. Device_Info.objects.filter(UID__in=uidList).delete()
  528. UidPushModel.objects.filter(uid_set__uid__in=uidList).delete()
  529. if '设备配置数据' in delDataOptions:
  530. UidSetModel.objects.filter(uid__in=uidList).delete()
  531. if '设备推送数据' in delDataOptions:
  532. EquipmentInfoService.delete_all_equipment_info(device_uid__in=uidList)
  533. if '设备AP信息数据' in delDataOptions:
  534. UidUserModel.objects.filter(UID__in=uidList).delete()
  535. if '设备AI数据' in delDataOptions:
  536. ExperienceAiModel.objects.filter(uid__in=uidList).delete()
  537. # Order_Model.objects.filter(UID__in=uidList, order_type=1).delete()
  538. if '设备云存数据' in delDataOptions:
  539. UID_Bucket.objects.filter(uid__in=uidList).delete()
  540. AiService.objects.filter(uid__in=uidList).delete()
  541. StsCrdModel.objects.filter(uid__in=uidList).delete()
  542. VodHlsModel.objects.filter(uid__in=uidList).delete()
  543. # 删除vod_hls分表数据
  544. split_vod_hls_obj = SplitVodHlsObject()
  545. split_vod_hls_obj.del_vod_hls_data(uid__in=uidList)
  546. Unused_Uid_Meal.objects.filter(uid__in=uidList).delete()
  547. ExperienceContextModel.objects.filter(uid__in=uidList).delete()
  548. # Order_Model.objects.filter(UID__in=uidList, order_type=0).delete()
  549. Device_Info.objects.filter(UID__in=uidList).update(vodPrimaryUserID='', vodPrimaryMaster='')
  550. # 上传序列号文件且选中序列号解绑uid
  551. # if serialNumberList is not None and '序列号解绑uid' in delDataOptions:
  552. # # 解绑uid数据
  553. # UIDModel.objects.filter(uid__in=uidList, status=2).update(status=0)
  554. # UIDCompanySerialModel.objects.filter(uid__uid__in=uidList).delete()
  555. # CompanySerialModel.objects.filter(serial_number__in=serial_number_list).update(status=1)
  556. # UidPushModel.objects.filter(uid_set__uid__in=uidList).delete()
  557. # # 序列号加入重置状态redis列表
  558. # redis_obj = RedisObject()
  559. # for serial in serial_number_list:
  560. # redis_obj.rpush(UNUSED_SERIAL_REDIS_LIST, serial)
  561. device_list = uidList if serialNumberList is None else serial_number_list
  562. log = {
  563. 'user_id': 2,
  564. 'status': 200,
  565. 'time': int(time.time()),
  566. 'url': 'deviceManagement/delDeviceData',
  567. 'content': json.dumps(content),
  568. 'ip': ip,
  569. 'operation': '删除数据的设备列表:{}'.format(device_list),
  570. }
  571. LogModel.objects.create(**log)
  572. return response.json(0)
  573. except Exception as e:
  574. log = {
  575. 'user_id': 2,
  576. 'status': 500,
  577. 'time': int(time.time()),
  578. 'url': 'deviceManagement/delDeviceData',
  579. 'content': json.dumps(content),
  580. 'ip': ip,
  581. 'operation': '删除数据失败的设备列表:{},{},{}'.format(device_list, e.__traceback__.tb_lineno, repr(e)),
  582. }
  583. LogModel.objects.create(**log)
  584. return response.json(500, 'error_line:{}, error_msg:{}'.format(e.__traceback__.tb_lineno, repr(e)))
  585. @staticmethod
  586. def deleteDeviceCache(uid_list):
  587. """
  588. 翻新重置时清楚验证用户UID缓存
  589. """
  590. try:
  591. redis = RedisObject(3)
  592. for item in uid_list:
  593. # 构建Redis键
  594. device_key = f"{RedisKeyConstant.BASIC_USER.value}{item['userID_id']}:UID:{item['UID']}"
  595. redis.del_data(device_key)
  596. except Exception as e:
  597. error_line = e.__traceback__.tb_lineno
  598. LOGGER.error(f'翻新重置异步清缓存异常:error_line:{error_line}, error_msg:{repr(e)}')
  599. def get_app_device_type_list(self, request_dict, response):
  600. app_bundle_name = request_dict.get('appBundleName', None)
  601. lang = request_dict.get('lang', None)
  602. model = request_dict.get('model', None)
  603. type = request_dict.get('type', None)
  604. name = request_dict.get('name', None)
  605. pageNo = request_dict.get('pageNo', None)
  606. pageSize = request_dict.get('pageSize', None)
  607. if not all([pageNo, pageSize]):
  608. return response.json(444)
  609. page = int(pageNo)
  610. line = int(pageSize)
  611. try:
  612. app_bundle_qs = AppBundle.objects.all()
  613. if app_bundle_name:
  614. app_bundle_id = self.app_name_convert_id([app_bundle_name])
  615. print(app_bundle_id)
  616. app_bundle_qs = app_bundle_qs.filter(id__in=app_bundle_id)
  617. if lang:
  618. app_bundle_qs = app_bundle_qs.filter(app_device_type__devicenamelanguage__lang=lang)
  619. app_bundle_qs = app_bundle_qs.annotate(
  620. model=F('app_device_type__model'), type=F('app_device_type__type'), icon=F('app_device_type__icon'),
  621. lang=F('app_device_type__devicenamelanguage__lang'), iconV2=F('app_device_type__iconV2'),
  622. name=F('app_device_type__devicenamelanguage__name'),
  623. sort=F('app_device_type__devicenamelanguage__sort')).values('id', 'app_device_type__id', 'model',
  624. 'type', 'icon', 'iconV2', 'app_bundle_id',
  625. 'app_device_type__devicenamelanguage__id',
  626. 'lang', 'name', 'sort',
  627. 'app_device_type__app_version_number_id',
  628. 'app_device_type__config').order_by(
  629. 'app_device_type__devicenamelanguage__sort')
  630. if not app_bundle_qs.exists():
  631. return response.json(0)
  632. if name:
  633. app_bundle_qs = app_bundle_qs.filter(name=name)
  634. if model:
  635. app_bundle_qs = app_bundle_qs.filter(model=model)
  636. if type:
  637. app_bundle_qs = app_bundle_qs.filter(type=type)
  638. total = app_bundle_qs.count()
  639. app_bundle_qs = app_bundle_qs[(page - 1) * line:page * line]
  640. app_device_type_list = []
  641. for app_bundle in app_bundle_qs:
  642. app_bundle['version_number'] = app_bundle.pop('app_device_type__app_version_number_id')
  643. app_device_type_list.append(app_bundle)
  644. return response.json(0, {'list': app_device_type_list, 'total': total})
  645. except Exception as e:
  646. print(e)
  647. return response.json(500, 'error_line:{}, error_msg:{}'.format(e.__traceback__.tb_lineno, repr(e)))
  648. @staticmethod
  649. def get_app_bundle_id_list(response):
  650. try:
  651. app_info_qs = App_Info.objects.filter().values('id', 'appBundleId', 'appName')
  652. appBundleIdList = list(app_info_qs)
  653. return response.json(0, {'list': appBundleIdList})
  654. except Exception as e:
  655. print(e)
  656. return response.json(500, 'error_line:{}, error_msg:{}'.format(e.__traceback__.tb_lineno, repr(e)))
  657. @staticmethod
  658. def batch_edit_app_device_type(request_dict, request, response):
  659. # app_device_type表数据
  660. app_device_type_id = request_dict.get('app_device_type__id', None)
  661. model = request_dict.get('model', None)
  662. type = request_dict.get('type', None)
  663. icon = request.FILES.get('icon', None)
  664. iconV2 = request.FILES.get('iconV2', None)
  665. # device_name_language表数据
  666. device_name_language_id = request_dict.get('app_device_type__devicenamelanguage__id', None)
  667. sort = request_dict.get('sort', None)
  668. version_number = request_dict.get('version_number', None)
  669. config = request_dict.get('config', None)
  670. now_time = int(time.time())
  671. if not all([app_device_type_id, device_name_language_id, model, type, sort, version_number]):
  672. return response.json(444)
  673. # 强制类型转换
  674. list_app_device_type_id = [int(item) for item in eval(app_device_type_id)]
  675. list_device_name_language_id = [int(item) for item in eval(device_name_language_id)]
  676. try:
  677. with transaction.atomic():
  678. if icon or iconV2:
  679. bucket_name = 'ansjerfilemanager'
  680. s3 = AmazonS3Util(AWS_ACCESS_KEY_ID[1], AWS_SECRET_ACCESS_KEY[1], AWS_SES_ACCESS_REGION)
  681. icon_path = ""
  682. icon_v2_path = ""
  683. # 处理 icon
  684. if icon:
  685. file_key = f'app/device_type_images/{now_time}_{icon.name}'
  686. icon_path = f'https://{bucket_name}.s3.amazonaws.com/{file_key}'
  687. s3.upload_file_obj(
  688. bucket_name,
  689. file_key,
  690. icon,
  691. {'ContentType': icon.content_type, 'ACL': 'public-read'}
  692. )
  693. # 处理 iconV2
  694. if iconV2:
  695. file_v2_key = f'app/device_type_images/{now_time}_v2_{iconV2.name}'
  696. icon_v2_path = f'https://{bucket_name}.s3.amazonaws.com/{file_v2_key}'
  697. s3.upload_file_obj(
  698. bucket_name,
  699. file_v2_key,
  700. iconV2,
  701. {'ContentType': iconV2.content_type, 'ACL': 'public-read'}
  702. )
  703. # 更新数据库
  704. update_fields = {
  705. 'model': model,
  706. 'type': type,
  707. 'app_version_number_id': version_number,
  708. }
  709. if config:
  710. try:
  711. config = json.loads(config)
  712. update_fields['config'] = config
  713. except ValueError:
  714. return response.json(444, 'config必须是一个json数据')
  715. if icon_path:
  716. update_fields['icon'] = icon_path
  717. if icon_v2_path:
  718. update_fields['iconV2'] = icon_v2_path
  719. AppDeviceType.objects.filter(id__in=list_app_device_type_id).update(**update_fields)
  720. else:
  721. # 没有上传文件的情况,只更新配置或基本信息
  722. update_fields = {
  723. 'model': model,
  724. 'type': type,
  725. 'app_version_number_id': version_number,
  726. }
  727. if config:
  728. try:
  729. config = json.loads(config)
  730. update_fields['config'] = config
  731. except ValueError:
  732. return response.json(444, 'config必须是一个json数据')
  733. AppDeviceType.objects.filter(id__in=list_app_device_type_id).update(**update_fields)
  734. DeviceNameLanguage.objects.filter(id__in=list_device_name_language_id).update(sort=sort)
  735. return response.json(0)
  736. except Exception as e:
  737. print(e)
  738. return response.json(500, 'error_line:{}, error_msg:{}'.format(e.__traceback__.tb_lineno, repr(e)))
  739. @staticmethod
  740. def edit_app_device_type(request_dict, request, response):
  741. # app_device_type表数据
  742. app_device_type_id = request_dict.get('app_device_type__id', None)
  743. model = request_dict.get('model', None)
  744. type = request_dict.get('type', None)
  745. icon = request.FILES.get('icon', None)
  746. iconV2 = request.FILES.get('iconV2', None)
  747. # device_name_language表数据
  748. device_name_language_id = request_dict.get('app_device_type__devicenamelanguage__id', None)
  749. lang = request_dict.get('lang', None)
  750. name = request_dict.get('name', None)
  751. sort = request_dict.get('sort', None)
  752. version_number = request_dict.get('version_number', None)
  753. config = request_dict.get('config', None)
  754. now_time = int(time.time())
  755. if not all([app_device_type_id, model, type, device_name_language_id, lang, name, sort]):
  756. return response.json(444)
  757. try:
  758. with transaction.atomic():
  759. app_device_type = AppDeviceType.objects.filter(id=app_device_type_id).first()
  760. if icon or iconV2:
  761. bucket_name = 'ansjerfilemanager'
  762. s3 = AmazonS3Util(AWS_ACCESS_KEY_ID[1], AWS_SECRET_ACCESS_KEY[1], AWS_SES_ACCESS_REGION)
  763. icon_path = app_device_type.icon
  764. icon_v2_path = app_device_type.iconV2
  765. if icon:
  766. icon_path = f'https://ansjerfilemanager.s3.amazonaws.com/app/device_type_images/{now_time}_{icon.name}'
  767. file_key = f'app/device_type_images/{now_time}_{icon.name}'
  768. s3.upload_file_obj(
  769. bucket_name,
  770. file_key,
  771. icon,
  772. {'ContentType': icon.content_type, 'ACL': 'public-read'})
  773. if iconV2:
  774. icon_v2_path = f'https://ansjerfilemanager.s3.amazonaws.com/app/device_type_images/{now_time}_v2_{iconV2.name}'
  775. file_v2_key = f'app/device_type_images/{now_time}_v2_{iconV2.name}'
  776. s3.upload_file_obj(
  777. bucket_name,
  778. file_v2_key,
  779. iconV2,
  780. {'ContentType': iconV2.content_type, 'ACL': 'public-read'})
  781. if config:
  782. try:
  783. config = json.loads(config)
  784. except:
  785. return response.json(444, 'config必须是一个json数据')
  786. AppDeviceType.objects.filter(id=app_device_type_id) \
  787. .update(model=model, type=type, icon=icon_path, iconV2=icon_v2_path,
  788. app_version_number_id=version_number, config=config)
  789. else:
  790. AppDeviceType.objects.filter(id=app_device_type_id) \
  791. .update(model=model, type=type, icon=icon_path, iconV2=icon_v2_path,
  792. app_version_number_id=version_number)
  793. else:
  794. if config:
  795. try:
  796. config = json.loads(config)
  797. except:
  798. return response.json(444, 'config必须是一个json数据')
  799. AppDeviceType.objects.filter(id=app_device_type_id) \
  800. .update(model=model, type=type, app_version_number_id=version_number,
  801. config=config)
  802. else:
  803. AppDeviceType.objects.filter(id=app_device_type_id) \
  804. .update(model=model, type=type, app_version_number_id=version_number)
  805. DeviceNameLanguage.objects.filter(id=device_name_language_id).update(lang=lang, name=name, sort=sort)
  806. return response.json(0)
  807. except Exception as e:
  808. print(e)
  809. return response.json(500, 'error_line:{}, error_msg:{}'.format(e.__traceback__.tb_lineno, repr(e)))
  810. @staticmethod
  811. def delete_app_device_type(request_dict, response):
  812. app_bundle_id = request_dict.get('appBundleId', None)
  813. app_device_type_id = request_dict.get('appDeviceTypeId', None)
  814. if not all([app_bundle_id, app_device_type_id]):
  815. return response.json(444)
  816. try:
  817. # 删除语言表
  818. DeviceNameLanguage.objects.filter(app_device_type_id=app_device_type_id).delete()
  819. # 删除多对多关系
  820. app_bundle_qs = AppBundle.objects.get(id=app_bundle_id)
  821. app_bundle_qs.app_device_type.remove(app_device_type_id)
  822. # 删除app类型表
  823. AppDeviceType.objects.filter(id=app_device_type_id).delete()
  824. return response.json(0)
  825. except Exception as e:
  826. print(e)
  827. return response.json(500, 'error_line:{}, error_msg:{}'.format(e.__traceback__.tb_lineno, repr(e)))
  828. @staticmethod
  829. def reset_all(request, request_dict, response):
  830. uid = request_dict.get('uid', None)
  831. if not uid:
  832. return response.json(444)
  833. try:
  834. # 记录操作日志
  835. ip = CommonService.get_ip_address(request)
  836. content = json.loads(json.dumps(request_dict))
  837. with transaction.atomic():
  838. # 删除主用户
  839. Device_Info.objects.filter(UID=uid).update(vodPrimaryUserID='', vodPrimaryMaster='')
  840. # 删除云存
  841. UID_Bucket.objects.filter(uid=uid).delete()
  842. Unused_Uid_Meal.objects.filter(uid=uid).delete()
  843. # Order_Model.objects.filter(UID=uid, order_type=0).delete()
  844. StsCrdModel.objects.filter(uid=uid).delete()
  845. VodHlsModel.objects.filter(uid=uid).delete()
  846. # 删除vod_hls分表数据
  847. split_vod_hls_obj = SplitVodHlsObject()
  848. split_vod_hls_obj.del_vod_hls_data(uid=uid)
  849. ExperienceContextModel.objects.filter(uid=uid).delete()
  850. # 删除AI
  851. ExperienceAiModel.objects.filter(uid=uid).delete()
  852. AiService.objects.filter(uid=uid).delete()
  853. log = {
  854. 'ip': ip,
  855. 'user_id': 2,
  856. 'status': 200,
  857. 'time': int(time.time()),
  858. 'url': 'deviceManagement/resetAll',
  859. 'content': json.dumps(content),
  860. 'operation': '{}重置所有'.format(uid),
  861. }
  862. LogModel.objects.create(**log)
  863. return response.json(0)
  864. except Exception as e:
  865. print(e)
  866. return response.json(500, 'error_line:{}, error_msg:{}'.format(e.__traceback__.tb_lineno, repr(e)))
  867. def add_app_device_type(self, request_dict, response, request):
  868. """
  869. 添加设备类型
  870. @param request_dict: 请求参数
  871. @request_dict appBundleName: app包名
  872. @request_dict versionNumber: app版本号
  873. @request_dict model: 设备类型
  874. @request_dict type: 设备型号
  875. @request_dict name: 设备名称
  876. @request_dict sort: 排序
  877. @request.FILES iconFile: 上传图标
  878. @param response: 响应对象
  879. """
  880. # app包名称
  881. app_bundle_name = request_dict.get('appBundleName', None)
  882. # 版本号
  883. version_number = request_dict.get('versionNumber', None)
  884. # app_device_type表数据
  885. model = request_dict.get('model', None)
  886. type = request_dict.get('type', None)
  887. # device_name_language表数据
  888. name = request_dict.get('name', None)
  889. sort = request_dict.get('sort', None)
  890. config = request_dict.get('config', None)
  891. # 上传图标
  892. file = request.FILES.get('iconFile', None)
  893. file_v2 = request.FILES.get('iconV2File', None)
  894. if config:
  895. config = json.loads(config)
  896. try:
  897. type = int(type)
  898. data_name = eval(name)
  899. app_bundle_name_list = app_bundle_name.split(',')
  900. app_bundle_id = self.app_name_convert_id(app_bundle_name_list)
  901. existing_records = []
  902. success_records = []
  903. need_upload = False # 标记是否需要上传文件
  904. # 先检查所有数据是否存在
  905. with transaction.atomic():
  906. for app_id in app_bundle_id:
  907. for k, v in data_name.items():
  908. app_bundle_qs = AppBundle.objects.filter(id=app_id,
  909. app_device_type__devicenamelanguage__lang=k,
  910. app_device_type__app_version_number_id=version_number,
  911. app_device_type__type=type,
  912. app_device_type__model=model)
  913. if app_bundle_qs.exists():
  914. app_bundle = app_bundle_qs.values("app_bundle_id").first()
  915. existing_record = {"app_bundle_id": app_bundle["app_bundle_id"], "type": type,
  916. "version_number": version_number, "lang": k, "model": model}
  917. existing_records.append(existing_record)
  918. else:
  919. need_upload = True # 发现至少一条记录不存在,需要上传文件
  920. # 如果需要上传文件
  921. if need_upload:
  922. with transaction.atomic():
  923. if file:
  924. fileName = file.name
  925. now_time = int(time.time())
  926. icon = f'https://ansjerfilemanager.s3.amazonaws.com/app/device_type_images/{now_time}_{fileName}'
  927. bucket_name = 'ansjerfilemanager'
  928. file_key = f'app/device_type_images/{now_time}_{fileName}'
  929. s3 = AmazonS3Util(AWS_ACCESS_KEY_ID[1], AWS_SECRET_ACCESS_KEY[1], AWS_SES_ACCESS_REGION)
  930. s3.upload_file_obj(bucket_name, file_key, file,
  931. {'ContentType': file.content_type, 'ACL': 'public-read'})
  932. if file_v2:
  933. fileV2Name = file_v2.name
  934. now_time = int(time.time())
  935. iconV2 = f'https://ansjerfilemanager.s3.amazonaws.com/app/device_type_images/{now_time}_v2_{fileV2Name}'
  936. bucket_name = 'ansjerfilemanager'
  937. file_v2_key = f'app/device_type_images/{now_time}_v2_{fileV2Name}'
  938. s3 = AmazonS3Util(AWS_ACCESS_KEY_ID[1], AWS_SECRET_ACCESS_KEY[1], AWS_SES_ACCESS_REGION)
  939. s3.upload_file_obj(bucket_name, file_v2_key, file_v2,
  940. {'ContentType': file_v2.content_type, 'ACL': 'public-read'})
  941. for app_id in app_bundle_id:
  942. for k, v in data_name.items():
  943. record_key = {"app_bundle_id": app_id, "type": type, "version_number": version_number,
  944. "lang": k, "model": model}
  945. # 检查这个组合的记录是否存在
  946. if not any(rec == record_key for rec in existing_records):
  947. app_bundle = AppBundle.objects.filter(id=app_id).values('id', 'app_bundle_id').first()
  948. app_device_type_qs = AppDeviceType.objects.create(model=model, type=type,
  949. icon=icon if file else "",
  950. iconV2=iconV2 if file_v2 else "",
  951. app_version_number_id=version_number,
  952. config=config)
  953. DeviceNameLanguage.objects.create(lang=k, name=v, sort=sort,
  954. app_device_type_id=app_device_type_qs.id)
  955. app_device_type_qs.appbundle_set.add(app_bundle["id"])
  956. success_records.append(
  957. {"app_bundle_id": app_bundle["app_bundle_id"], "type": type,
  958. "version_number": version_number,
  959. "lang": k, "model": model}
  960. )
  961. response_data = {
  962. 'success_records': success_records,
  963. 'existing_records': existing_records
  964. }
  965. return response.json(0, response_data)
  966. except Exception as e:
  967. print(e)
  968. return response.json(500, 'error_line:{}, error_msg:{}'.format(e.__traceback__.tb_lineno, repr(e)))
  969. @staticmethod
  970. def get_device_icon(request_dict, response):
  971. """
  972. 查询设备信息图标
  973. @param request_dict: 请求参数
  974. @request_dict lang: 语言
  975. @request_dict app_bundle_id: app版本id
  976. @request_dict version_number: app版本号
  977. @param response: 响应对象
  978. @return:
  979. """
  980. lang = request_dict.get('lang', 'en')
  981. app_bundle_id = request_dict.get('appBundleId', None)
  982. version_number = request_dict.get('versionNumber', None)
  983. # 查询设备信息图标
  984. api_version = request_dict.get('apiVersion', None)
  985. if not all([lang, app_bundle_id, version_number]):
  986. return response.json(444)
  987. try:
  988. # tc是ios繁体字语言类型
  989. if lang == 'tc':
  990. lang = 'cn_tw'
  991. app_bundle_qs = AppBundle.objects.filter(app_bundle_id=app_bundle_id).values(
  992. 'app_device_type__app_version_number_id').distinct().order_by('app_device_type__app_version_number_id')
  993. # 判断版本是否存在, 不存在则获取输入版本范围内最接近的输入版本
  994. version_number_list = []
  995. app_bundle_list = []
  996. for version in app_bundle_qs:
  997. version_number_list.append(version['app_device_type__app_version_number_id'])
  998. new_version_number = CommonService.compare_version_number(version_number, version_number_list)
  999. app_device_qs = DeviceNameLanguage.objects.filter(lang=lang)
  1000. if not app_device_qs.exists():
  1001. lang = 'en'
  1002. # 版本号对应的设备信息图标
  1003. for version_number in new_version_number:
  1004. app_bundle_qs = AppBundle.objects.filter(app_bundle_id=app_bundle_id,
  1005. app_device_type__devicenamelanguage__lang=lang,
  1006. app_device_type__app_version_number_id=version_number). \
  1007. annotate(
  1008. model=F('app_device_type__model'), type=F('app_device_type__type'), icon=F('app_device_type__icon'),
  1009. name=F('app_device_type__devicenamelanguage__name'), iconV2=F('app_device_type__iconV2'),
  1010. sort=F('app_device_type__devicenamelanguage__sort'),
  1011. config=F('app_device_type__config'),
  1012. app_version_number_id=F('app_device_type__app_version_number_id')).values('model', 'type', 'icon',
  1013. 'name', 'sort', 'config',
  1014. 'iconV2',
  1015. 'app_device_type__app_version_number_id')
  1016. # 使用lang="en"来补全缺失的数据
  1017. en_lang_qs = AppBundle.objects.filter(
  1018. app_bundle_id=app_bundle_id,
  1019. app_device_type__devicenamelanguage__lang="en",
  1020. app_device_type__app_version_number_id=version_number
  1021. ).annotate(
  1022. model=F('app_device_type__model'),
  1023. type=F('app_device_type__type'),
  1024. icon=F('app_device_type__icon'),
  1025. name=F('app_device_type__devicenamelanguage__name'),
  1026. iconV2=F('app_device_type__iconV2'),
  1027. sort=F('app_device_type__devicenamelanguage__sort'),
  1028. config=F('app_device_type__config'),
  1029. app_version_number_id=F('app_device_type__app_version_number_id')
  1030. ).values('model', 'type', 'icon', 'name', 'sort', 'config', 'iconV2',
  1031. 'app_device_type__app_version_number_id')
  1032. # 转换查询集为字典
  1033. current_lang_data = {item['type']: item for item in app_bundle_qs}
  1034. en_lang_data = {item['type']: item for item in en_lang_qs}
  1035. # 合并数据,优先使用当前语言的数据,缺少的字段用英文补充
  1036. for type, en_data in en_lang_data.items():
  1037. current_data = current_lang_data.get(type, {})
  1038. merged_data = {
  1039. 'type': en_data['type'],
  1040. 'model': current_data.get('model', en_data['model']),
  1041. 'icon': current_data.get('icon', en_data['icon']),
  1042. 'name': current_data.get('name', en_data['name']),
  1043. 'sort': current_data.get('sort', en_data['sort']),
  1044. 'config': current_data.get('config', en_data['config']),
  1045. 'iconV2': current_data.get('iconV2', en_data['iconV2']),
  1046. 'app_device_type__app_version_number_id': current_data.get(
  1047. 'app_device_type__app_version_number_id',
  1048. en_data['app_device_type__app_version_number_id']),
  1049. }
  1050. if api_version == "V2":
  1051. app_bundle_list.append({
  1052. 'model': merged_data['model'],
  1053. 'type': merged_data['type'],
  1054. 'icon': merged_data['iconV2'] if merged_data['iconV2'] != "" else merged_data['icon'],
  1055. 'name': merged_data['name'],
  1056. 'sort': merged_data['sort'],
  1057. 'config': merged_data['config'],
  1058. 'app_device_type__app_version_number_id': merged_data['app_device_type__app_version_number_id'],
  1059. })
  1060. else:
  1061. app_bundle_list.append({
  1062. 'model': merged_data['model'],
  1063. 'type': merged_data['type'],
  1064. 'icon': merged_data['icon'],
  1065. 'name': merged_data['name'],
  1066. 'sort': merged_data['sort'],
  1067. 'config': merged_data['config'],
  1068. 'app_device_type__app_version_number_id': merged_data[
  1069. 'app_device_type__app_version_number_id'],
  1070. })
  1071. dvr_list = [app_bundle for app_bundle in app_bundle_list if app_bundle['model'] == 1]
  1072. ipc_list = [app_bundle for app_bundle in app_bundle_list if app_bundle['model'] == 2]
  1073. res = {
  1074. 'deviceDvr': sorted(dvr_list, key=operator.itemgetter('sort')),
  1075. 'deviceIpc': sorted(ipc_list, key=operator.itemgetter('sort')),
  1076. }
  1077. return response.json(0, res)
  1078. except Exception as e:
  1079. print(e)
  1080. return response.json(500, 'error_line:{}, error_msg:{}'.format(e.__traceback__.tb_lineno, repr(e)))
  1081. @staticmethod
  1082. def get_uid_push(request_dict, response):
  1083. """
  1084. 查询设备信息详情信息
  1085. @param request_dict: 请求参数
  1086. @request_dict UID: UID
  1087. @param response: 响应对象
  1088. @return:
  1089. """
  1090. uid = request_dict.get('UID', None)
  1091. if not uid:
  1092. return response.json(444)
  1093. try:
  1094. uid_set_qs = UidSetModel.objects.filter(uid=uid).first()
  1095. data = model_to_dict(uid_set_qs)
  1096. ALGORITHM_COMBO_TYPES = ['移动', '人形', '车型', '宠物', '人脸', '异响', '闯入', '离开', '徘徊', '无人',
  1097. '往来', '哭声', '手势', '火焰', '婴儿', '包裹', '暂无', '电动车', '遮挡']
  1098. if data['ai_type'] > 0:
  1099. num = data['ai_type']
  1100. result = ""
  1101. while num != 0:
  1102. ret = num % 2
  1103. num //= 2
  1104. result = str(ret) + result
  1105. types = []
  1106. event_type = result
  1107. len_type = len(event_type)
  1108. for i in range(len_type):
  1109. e_type = event_type[len_type - 1 - i]
  1110. if e_type == '1':
  1111. types.append(str(ALGORITHM_COMBO_TYPES[i]))
  1112. data['ai_type'] = types
  1113. # uid_set查uid_push
  1114. uid_pushes_qs = UidPushModel.objects.filter(uid_set_id=uid_set_qs.id).select_related('userID')
  1115. uid_push_data = []
  1116. # 保存uid_pushes_qs列表
  1117. for item in uid_pushes_qs:
  1118. item_dict = model_to_dict(item)
  1119. # 添加 username 字段
  1120. item_dict['username'] = item.userID.username if item.userID else None
  1121. uid_push_data.append(item_dict)
  1122. data["uid_push"] = uid_push_data
  1123. return response.json(0, data)
  1124. except Exception as e:
  1125. print(e)
  1126. return response.json(500, 'error_line:{}, error_msg:{}'.format(e.__traceback__.tb_lineno, repr(e)))
  1127. @staticmethod
  1128. def get_app_name_list(response):
  1129. """
  1130. 查询APP包名称列表
  1131. @param response: 响应对象
  1132. @return:
  1133. """
  1134. try:
  1135. app_bundle_qs = AppBundle.objects.all().values_list('app_bundle_id')
  1136. app_info = App_Info.objects.filter(appBundleId__in=app_bundle_qs).values('appName')
  1137. app_name_list = []
  1138. for app_name in app_info:
  1139. app_name_list.append(app_name['appName'])
  1140. app_name_list = list(set(app_name_list))
  1141. return response.json(0, app_name_list)
  1142. except Exception as e:
  1143. print(e)
  1144. return response.json(500, 'error_line:{}, error_msg:{}'.format(e.__traceback__.tb_lineno, repr(e)))
  1145. @staticmethod
  1146. def app_name_convert_id(app_name_list):
  1147. """
  1148. app_name_list 转 app_id_list
  1149. @param app_name_list: app名字列表
  1150. @return app_id_list: app id列表
  1151. """
  1152. try:
  1153. app_bundle_id_list = App_Info.objects.filter(appName__in=app_name_list).values_list('appBundleId',
  1154. flat=True)
  1155. app_id_list = AppBundle.objects.filter(app_bundle_id__in=app_bundle_id_list).values_list('id', flat=True)
  1156. return list(set(app_id_list))
  1157. except Exception as e:
  1158. print(e)
  1159. return []
  1160. @staticmethod
  1161. def call_add_app_device_type(request_dict, response, request):
  1162. """
  1163. 添加设备类型
  1164. @param request_dict: 请求参数
  1165. @request_dict appBundleName: app包名
  1166. @request_dict versionNumber: app版本号
  1167. @request_dict model: 设备类型
  1168. @request_dict type: 设备型号
  1169. @request_dict name: 设备名字
  1170. @request_dict sort: 排序
  1171. @request_dict region: 地区
  1172. @request.FILES iconFile: 上传图标
  1173. @param response: 响应对象
  1174. """
  1175. # app包名称
  1176. app_bundle_name = request_dict.get('appBundleName', None)
  1177. # 版本号
  1178. version_number = request_dict.get('versionNumber', None)
  1179. # app_device_type表数据
  1180. model = request_dict.get('model', None)
  1181. type = request_dict.get('type', None)
  1182. # device_name_language表数据
  1183. name = request_dict.get('name', None)
  1184. sort = request_dict.get('sort', None)
  1185. config = request_dict.get('config', None)
  1186. # 上传图标
  1187. files = request.FILES.get('iconFile', None)
  1188. # 上传图标
  1189. files_v2 = request.FILES.get('iconV2File', None)
  1190. # 需要添加到哪一个服
  1191. region = request_dict.get("region", None) # 获取需要同步的区域
  1192. # 检查必需参数
  1193. if not all([model, type, name, sort, version_number, app_bundle_name, region]):
  1194. return response.json(444, 'Missing required parameters')
  1195. if files is None and files_v2 is None:
  1196. return response.json(444, 'Missing required parameters')
  1197. LOGGER.info(f"添加图标设备类型 region: {region} -- region")
  1198. regions = region.split(",") # 将同步区域拆分为列表
  1199. return_value_list = []
  1200. LOGGER.info(f"添加图标设备类型 regions: {regions} -- regions列表")
  1201. for region in regions:
  1202. if region == 'test':
  1203. url = SERVER_DOMAIN_TEST
  1204. elif region == 'cn':
  1205. url = SERVER_DOMAIN_CN
  1206. elif region == 'us':
  1207. url = SERVER_DOMAIN_US
  1208. elif region == 'eu':
  1209. url = SERVER_DOMAIN_EUR
  1210. else:
  1211. return response.json(444, 'Invalid region')
  1212. LOGGER.info(f"添加图标设备类型 url: {url} -- 确定url")
  1213. try:
  1214. form_data = {
  1215. 'name': name,
  1216. 'type': type,
  1217. 'sort': sort,
  1218. 'model': model,
  1219. 'versionNumber': version_number,
  1220. 'appBundleName': app_bundle_name,
  1221. }
  1222. if config:
  1223. try:
  1224. config = json.loads(config)
  1225. except:
  1226. return response.json(444, 'config必须是一个json数据')
  1227. form_data["config"] = json.dumps(config)
  1228. # 每次循环都重新读取文件内容并构造新的文件对象
  1229. if files:
  1230. files.seek(0)
  1231. file_content = files.read()
  1232. files_for_post = {'iconFile': ('icon.png', io.BytesIO(file_content), files.content_type)}
  1233. else:
  1234. files_for_post = {}
  1235. if files_v2:
  1236. files_v2.seek(0)
  1237. file_content_v2 = files_v2.read()
  1238. files_for_post['iconV2File'] = ('iconV2.png', io.BytesIO(file_content_v2), files_v2.content_type)
  1239. # 发送 POST 请求调用 add_app_device_type 方法
  1240. LOGGER.info(f"添加图标设备类型 url: {url} -- 准备发送")
  1241. response_value = requests.post(url + "/deviceManagement/addAppDeviceType",
  1242. data=form_data,
  1243. files=files_for_post)
  1244. return_value = {region: response_value.json()["data"]}
  1245. return_value_list.append(return_value)
  1246. except Exception as e:
  1247. return response.json(500, 'error_line:{}, error_msg:{}'.format(e.__traceback__.tb_lineno, repr(e)))
  1248. return response.json(0, {"list": return_value_list})
  1249. @classmethod
  1250. def query_device_user(cls, request, request_dict, response):
  1251. try:
  1252. # 从请求中检索文件
  1253. file = request.FILES.get('deviceFile')
  1254. file_type = int(request_dict.get('type', 1))
  1255. uid_list = []
  1256. if not file:
  1257. return response.json(444)
  1258. device_info_list = []
  1259. # 处理文件内容并生成设备信息列表
  1260. # 序列号
  1261. if file_type == 2:
  1262. for item in file:
  1263. item = item.decode().strip().replace(" ", "")
  1264. serial = item[:6]
  1265. # 请求序列号系统查询获取序列号记录
  1266. url = 'http://{}/serialNumber/checkSerialLog'.format(SERIAL_DOMAIN_NAME)
  1267. params = {'serial': serial}
  1268. r = requests.get(url=url, params=params, timeout=5)
  1269. assert r.status_code == 200
  1270. result = eval(r.content)
  1271. is_reset = 0 if result['code'] == 0 else 1
  1272. uid = CommonService.get_uid_by_serial_number(serial)
  1273. # 序列号没绑定uid,需要重置
  1274. if uid == serial:
  1275. is_reset = 1
  1276. uid, device_name, ip, username = '', '', '', ''
  1277. else:
  1278. # 根据uid查询设备信息
  1279. device_name, ip, username = cls.get_device_info(uid)
  1280. device_info_data = {
  1281. 'isReset': is_reset,
  1282. 'uid': uid,
  1283. 'serialNumber': item,
  1284. 'deviceName': device_name,
  1285. 'ip': ip,
  1286. 'uName': username
  1287. }
  1288. device_info_list.append(device_info_data)
  1289. # uid
  1290. else:
  1291. for item in file:
  1292. uid = item.decode().strip().replace(" ", "")
  1293. is_reset = 0
  1294. serial_number = CommonService.get_serial_number_by_uid(uid)
  1295. if serial_number == uid:
  1296. serial_number = ''
  1297. device_name, ip, username = cls.get_device_info(uid)
  1298. device_info_data = {
  1299. 'isReset': is_reset,
  1300. 'uid': uid,
  1301. 'serialNumber': serial_number,
  1302. 'deviceName': device_name,
  1303. 'ip': ip,
  1304. 'uName': username
  1305. }
  1306. device_info_list.append(device_info_data)
  1307. # 返回带有用户信息的响应
  1308. return response.json(0, {'userInfo': device_info_list})
  1309. except Exception as e:
  1310. return response.json(500, 'error_line:{}, error_msg:{}'.format(e.__traceback__.tb_lineno, repr(e)))
  1311. @staticmethod
  1312. def get_device_info(uid):
  1313. """
  1314. 根据uid查询设备信息
  1315. :param uid:
  1316. :return: device_name, ip, username
  1317. """
  1318. device_name, ip, username = '', '', ''
  1319. device_info_qs = Device_Info.objects.filter(UID=uid).values('NickName', 'ip', 'userID__username')
  1320. if device_info_qs.exists():
  1321. device_name = device_info_qs[0]['NickName']
  1322. ip = device_info_qs[0]['ip']
  1323. username = device_info_qs[0]['userID__username']
  1324. return device_name, ip, username
  1325. @staticmethod
  1326. def get_customer_device_list(request_dict, response):
  1327. """
  1328. 查询扫码添加设备列表
  1329. :param request_dict:
  1330. :param response:
  1331. :return:
  1332. """
  1333. order_number = request_dict.get('orderNumber')
  1334. name = request_dict.get('name')
  1335. email = request_dict.get('email')
  1336. serial_number = request_dict.get('serialNumber')
  1337. uid = request_dict.get('uid')
  1338. page = int(request_dict.get('pageNo', 0)) # 默认值设为 0
  1339. page_size = int(request_dict.get('pageSize', 0)) # 默认值设为 0
  1340. try:
  1341. # 构建查询条件
  1342. custom_customer_qs = CustomCustomerOrderInfo.objects.all()
  1343. if order_number:
  1344. custom_customer_qs = custom_customer_qs.filter(order_number__icontains=order_number)
  1345. if name:
  1346. custom_customer_qs = custom_customer_qs.filter(name__icontains=name)
  1347. if email:
  1348. custom_customer_qs = custom_customer_qs.filter(email__icontains=email)
  1349. # 获取所需的ID和数量
  1350. c_id_list = custom_customer_qs.values_list("id", flat=True)
  1351. total_quantity = custom_customer_qs.aggregate(total_quantity=Sum('quantity'))['total_quantity']
  1352. # 查询设备列表
  1353. customer_device_qs = CustomCustomerDevice.objects.filter(c_id__in=c_id_list).order_by('-created_time')
  1354. # 通过serial_number和uid进行过滤
  1355. if serial_number:
  1356. customer_device_qs = customer_device_qs.filter(serial_number__icontains=serial_number)
  1357. if uid:
  1358. customer_device_qs = customer_device_qs.filter(uid=uid)
  1359. # 分页处理
  1360. if page > 0 and page_size > 0:
  1361. paginator = Paginator(customer_device_qs, page_size)
  1362. customer_device_page = paginator.get_page(page)
  1363. customer_device_list = customer_device_page.object_list
  1364. total = paginator.count
  1365. else:
  1366. customer_device_list = list(customer_device_qs)
  1367. total = customer_device_qs.count()
  1368. # 创建一个字典来映射 c_id 到 CustomCustomerOrderInfo 对象
  1369. customer_order_map = {order.id: order for order in custom_customer_qs}
  1370. # 构建设备列表
  1371. result_list = []
  1372. for device in customer_device_list:
  1373. customer_order = customer_order_map.get(device.c_id)
  1374. if customer_order:
  1375. result_list.append({
  1376. 'id': device.id,
  1377. 'serialNumber': device.serial_number,
  1378. 'uid': device.uid,
  1379. 'deviceType': device.type,
  1380. 'fullCode': device.full_code,
  1381. 'addTime': device.created_time,
  1382. 'orderNumber': customer_order.order_number,
  1383. 'name': customer_order.name,
  1384. 'email': customer_order.email,
  1385. })
  1386. else:
  1387. result_list.append({
  1388. 'id': device.id,
  1389. 'serialNumber': device.serial_number,
  1390. 'uid': device.uid,
  1391. 'deviceType': device.type,
  1392. 'fullCode': device.full_code,
  1393. 'addTime': device.created_time,
  1394. 'orderNumber': "",
  1395. 'name': "",
  1396. 'email': "",
  1397. })
  1398. # 构造返回数据
  1399. data = {
  1400. 'total': total,
  1401. 'orderDeviceQuantity': total_quantity or 0, # 防止为None
  1402. 'list': result_list,
  1403. }
  1404. return response.json(0, data)
  1405. except Exception as e:
  1406. return response.json(500, f'error_line:{e.__traceback__.tb_lineno}, error_msg:{repr(e)}')
  1407. @staticmethod
  1408. def get_device_ver_info(request_dict, response):
  1409. d_code = request_dict.get('dCode', None)
  1410. software_ver = request_dict.get('softwareVer', None)
  1411. device_type = request_dict.get('deviceType', None)
  1412. page = request_dict.get('pageNo', 1) # 当前页码,默认为1
  1413. page_size = request_dict.get('pageSize', 10) # 每页显示的记录数,默认为10
  1414. if not all([page, page_size]):
  1415. return response.json(444)
  1416. try:
  1417. device_ver_info_qs = DeviceVersionInfo.objects.all()
  1418. if d_code:
  1419. device_ver_info_qs = device_ver_info_qs.filter(d_code__icontains=d_code)
  1420. if software_ver:
  1421. device_ver_info_qs = device_ver_info_qs.filter(software_ver__icontains=software_ver)
  1422. if device_type:
  1423. device_ver_info_qs = device_ver_info_qs.filter(device_type=device_type)
  1424. # 对TimeAlbum结果进行分页
  1425. paginator = Paginator(device_ver_info_qs.order_by("-id"), page_size)
  1426. device_ver_infos = paginator.page(page) # 获取当前页的数据
  1427. device_ver_info_list = []
  1428. # 对每个TimeAlbum,查询相关的AlbumMedia
  1429. for device_ver_info in device_ver_infos:
  1430. device_ver_info_list.append(
  1431. {
  1432. 'deviceVerId': device_ver_info.id,
  1433. 'dCode': device_ver_info.d_code,
  1434. 'softwareVer': device_ver_info.software_ver,
  1435. 'firmwareVer': device_ver_info.firmware_ver,
  1436. 'videoCode': device_ver_info.video_code,
  1437. 'regionAlexa': device_ver_info.region_alexa,
  1438. 'supportsHumanTracking': device_ver_info.supports_human_tracking,
  1439. 'supportsCustomVoice': device_ver_info.supports_custom_voice,
  1440. 'supportsDualBandWifi': device_ver_info.supports_dual_band_wifi,
  1441. 'supportsFourPoint': device_ver_info.supports_four_point,
  1442. 'supports4g': device_ver_info.supports_4g,
  1443. 'supportsPTZ': device_ver_info.supports_ptz,
  1444. 'supportsAi': device_ver_info.supports_ai,
  1445. 'supportsCloudStorage': device_ver_info.supports_cloud_storage,
  1446. 'supportsAlexa': device_ver_info.supports_alexa,
  1447. 'deviceType': device_ver_info.device_type,
  1448. 'resolution': device_ver_info.resolution,
  1449. 'aiType': device_ver_info.ai_type,
  1450. 'supportsAlarm': device_ver_info.supports_alarm,
  1451. 'supportsNightVision': device_ver_info.supports_night_vision,
  1452. 'screenChannels': device_ver_info.screen_channels,
  1453. 'networkType': device_ver_info.network_type,
  1454. 'otherFeatures': device_ver_info.other_features,
  1455. 'electricityStatistics': device_ver_info.electricity_statistics,
  1456. 'supportsPetTracking': device_ver_info.supports_pet_tracking,
  1457. 'has4gCloud': device_ver_info.has_4g_cloud,
  1458. 'createdTime': device_ver_info.created_time,
  1459. 'updatedTime': device_ver_info.updated_time
  1460. }
  1461. )
  1462. return response.json(0, {
  1463. 'total': paginator.count,
  1464. 'list': device_ver_info_list,
  1465. })
  1466. except Exception as e:
  1467. print(e)
  1468. return response.json(500, 'error_line:{}, error_msg:{}'.format(e.__traceback__.tb_lineno, repr(e)))
  1469. @staticmethod
  1470. def add_device_ver_info(request_dict, response):
  1471. d_code = request_dict.get('dCode', None)
  1472. software_ver = request_dict.get('softwareVer', None)
  1473. firmware_ver = request_dict.get('firmwareVer', "")
  1474. video_code = request_dict.get('videoCode', None)
  1475. region_alexa = request_dict.get('regionAlexa', "")
  1476. supports_human_tracking = request_dict.get('supportsHumanTracking', 0)
  1477. supports_custom_voice = request_dict.get('supportsCustomVoice', 0)
  1478. supports_dual_band_wifi = request_dict.get('supportsDualBandWifi', 0)
  1479. supports_four_point = request_dict.get('supportsFourPoint', 0)
  1480. supports_4g = request_dict.get('supports4g', 0)
  1481. supports_ptz = request_dict.get('supportsPTZ', 0)
  1482. supports_ai = request_dict.get('supportsAi', 0)
  1483. supports_cloud_storage = request_dict.get('supportsCloudStorage', 0)
  1484. supports_alexa = request_dict.get('supportsAlexa', 0)
  1485. device_type = request_dict.get('deviceType', None)
  1486. resolution = request_dict.get('resolution', "")
  1487. ai_type = request_dict.get('aiType', 0)
  1488. supports_alarm = request_dict.get('supportsAlarm', None)
  1489. supports_night_vision = request_dict.get('supportsNightVision', 0)
  1490. screen_channels = request_dict.get('screenChannels', None)
  1491. network_type = request_dict.get('networkType', None)
  1492. electricity_statistics = request_dict.get('electricityStatistics', 0)
  1493. supports_pet_tracking = request_dict.get('supportsPetTracking', 0)
  1494. has_4g_cloud = request_dict.get('has4gCloud', -1)
  1495. other_features_fields = [
  1496. 'supports_lighting',
  1497. 'is_support_multi_speed',
  1498. 'supports_algorithm_switch',
  1499. 'supports_playback_filtering'
  1500. ]
  1501. check_other_features = request_dict.get('otherFeatures', None)
  1502. if check_other_features:
  1503. try:
  1504. other_features = json.loads(check_other_features)
  1505. for field in other_features_fields:
  1506. if field not in other_features or other_features[field] in (None, '', []):
  1507. other_features[field] = -1
  1508. LOGGER.info(f'设置 {field} 为默认值 -1')
  1509. except json.JSONDecodeError:
  1510. LOGGER.error(f"otherFeatures JSON 解析失败: {check_other_features}")
  1511. return response.json(500, "json无效")
  1512. else:
  1513. other_features = {field: -1 for field in other_features_fields}
  1514. LOGGER.info(f'未传入otherFeatures,创建默认值字典: {other_features}')
  1515. if not all([d_code, software_ver, video_code,
  1516. device_type, supports_alarm,
  1517. screen_channels, network_type]
  1518. ):
  1519. return response.json(444)
  1520. try:
  1521. now_time = int(time.time())
  1522. ai_type = int(ai_type)
  1523. if DeviceVersionInfo.objects.filter(d_code=d_code, software_ver=software_ver).exists():
  1524. return response.json(174)
  1525. DeviceVersionInfo.objects.create(
  1526. d_code=d_code,
  1527. software_ver=software_ver,
  1528. firmware_ver=firmware_ver,
  1529. video_code=video_code,
  1530. region_alexa=region_alexa,
  1531. supports_human_tracking=supports_human_tracking,
  1532. supports_custom_voice=supports_custom_voice,
  1533. supports_dual_band_wifi=supports_dual_band_wifi,
  1534. supports_four_point=supports_four_point,
  1535. supports_4g=supports_4g,
  1536. supports_ptz=supports_ptz,
  1537. supports_ai=supports_ai,
  1538. supports_cloud_storage=supports_cloud_storage,
  1539. supports_alexa=supports_alexa,
  1540. device_type=device_type,
  1541. resolution=resolution,
  1542. ai_type=ai_type,
  1543. supports_alarm=supports_alarm,
  1544. supports_night_vision=supports_night_vision,
  1545. screen_channels=screen_channels,
  1546. network_type=network_type,
  1547. other_features=other_features,
  1548. electricity_statistics=electricity_statistics,
  1549. supports_pet_tracking=supports_pet_tracking,
  1550. has_4g_cloud=has_4g_cloud,
  1551. created_time=now_time,
  1552. updated_time=now_time
  1553. )
  1554. except Exception as e:
  1555. print(e)
  1556. return response.json(500, 'error_line:{}, error_msg:{}'.format(e.__traceback__.tb_lineno, repr(e)))
  1557. return response.json(0)
  1558. @staticmethod
  1559. def edit_device_ver_info(request_dict, response):
  1560. device_ver_id = request_dict.get('deviceVerId', None)
  1561. firmware_ver = request_dict.get('firmwareVer', "")
  1562. video_code = request_dict.get('videoCode', None)
  1563. region_alexa = request_dict.get('regionAlexa', "")
  1564. supports_human_tracking = request_dict.get('supportsHumanTracking', 0)
  1565. supports_custom_voice = request_dict.get('supportsCustomVoice', 0)
  1566. supports_dual_band_wifi = request_dict.get('supportsDualBandWifi', 0)
  1567. supports_four_point = request_dict.get('supportsFourPoint', 0)
  1568. supports_4g = request_dict.get('supports4g', 0)
  1569. supports_ptz = request_dict.get('supportsPTZ', 0)
  1570. supports_ai = request_dict.get('supportsAi', 0)
  1571. supports_cloud_storage = request_dict.get('supportsCloudStorage', 0)
  1572. supports_alexa = request_dict.get('supportsAlexa', 0)
  1573. device_type = request_dict.get('deviceType', None)
  1574. resolution = request_dict.get('resolution', "")
  1575. ai_type = request_dict.get('aiType', 0)
  1576. supports_alarm = request_dict.get('supportsAlarm', None)
  1577. supports_night_vision = request_dict.get('supportsNightVision', 0)
  1578. screen_channels = request_dict.get('screenChannels', None)
  1579. network_type = request_dict.get('networkType', None)
  1580. electricity_statistics = request_dict.get('electricityStatistics', 0)
  1581. supports_pet_tracking = request_dict.get('supportsPetTracking', 0)
  1582. has_4g_cloud = request_dict.get('has4gCloud', -1)
  1583. other_features_fields = [
  1584. 'supports_lighting',
  1585. 'is_support_multi_speed',
  1586. 'supports_algorithm_switch',
  1587. 'supports_playback_filtering'
  1588. ]
  1589. check_other_features = request_dict.get('otherFeatures', None)
  1590. if check_other_features:
  1591. try:
  1592. other_features = json.loads(check_other_features)
  1593. for field in other_features_fields:
  1594. if field not in other_features or other_features[field] in (None, '', []):
  1595. other_features[field] = -1
  1596. LOGGER.info(f'设置 {field} 为默认值 -1')
  1597. except json.JSONDecodeError:
  1598. LOGGER.error(f"otherFeatures JSON 解析失败: {check_other_features}")
  1599. return response.json(500, "json无效")
  1600. else:
  1601. other_features = {field: -1 for field in other_features_fields}
  1602. LOGGER.info(f'未传入otherFeatures,创建默认值字典: {other_features}')
  1603. if not all([device_ver_id, video_code, device_type, supports_alarm, screen_channels, network_type]):
  1604. return response.json(444)
  1605. try:
  1606. now_time = int(time.time())
  1607. ai_type = int(ai_type)
  1608. device_version_info_qs = DeviceVersionInfo.objects.filter(id=device_ver_id).values('d_code', 'software_ver')
  1609. if not device_version_info_qs.exists():
  1610. return response.json(173)
  1611. d_code = device_version_info_qs[0]['d_code']
  1612. software_ver = device_version_info_qs[0]['software_ver']
  1613. version_key = RedisKeyConstant.ZOSI_DEVICE_VERSION_INFO.value + software_ver + d_code
  1614. # 创建Redis对象
  1615. redis = RedisObject()
  1616. # 尝试从Redis中获取数据
  1617. version_info = redis.get_data(version_key)
  1618. if version_info:
  1619. # 如果在Redis中找到了数据,删除缓存
  1620. redis.del_data(version_key)
  1621. device_version_info_qs.update(
  1622. firmware_ver=firmware_ver,
  1623. video_code=video_code,
  1624. region_alexa=region_alexa,
  1625. supports_human_tracking=supports_human_tracking,
  1626. supports_custom_voice=supports_custom_voice,
  1627. supports_dual_band_wifi=supports_dual_band_wifi,
  1628. supports_four_point=supports_four_point,
  1629. supports_4g=supports_4g,
  1630. supports_ptz=supports_ptz,
  1631. supports_ai=supports_ai,
  1632. supports_cloud_storage=supports_cloud_storage,
  1633. supports_alexa=supports_alexa,
  1634. device_type=device_type,
  1635. resolution=resolution,
  1636. ai_type=ai_type,
  1637. supports_alarm=supports_alarm,
  1638. supports_night_vision=supports_night_vision,
  1639. screen_channels=screen_channels,
  1640. network_type=network_type,
  1641. other_features=other_features,
  1642. electricity_statistics=electricity_statistics,
  1643. supports_pet_tracking=supports_pet_tracking,
  1644. has_4g_cloud=has_4g_cloud,
  1645. created_time=now_time,
  1646. updated_time=now_time
  1647. )
  1648. return response.json(0)
  1649. except Exception as e:
  1650. print(e)
  1651. return response.json(500, 'error_line:{}, error_msg:{}'.format(e.__traceback__.tb_lineno, repr(e)))
  1652. @staticmethod
  1653. def del_device_ver_info(request_dict, response):
  1654. device_ver_id = request_dict.get('deviceVerId', None)
  1655. if not device_ver_id:
  1656. return response.json(444)
  1657. device_version_info_qs = DeviceVersionInfo.objects.filter(id=device_ver_id)
  1658. if not device_version_info_qs.exists():
  1659. return response.json(174)
  1660. device_version_info = device_version_info_qs.first() # Get the first instance
  1661. d_code = device_version_info.d_code
  1662. software_ver = device_version_info.software_ver
  1663. version_key = RedisKeyConstant.ZOSI_DEVICE_VERSION_INFO.value + software_ver + d_code
  1664. # 创建Redis对象
  1665. redis = RedisObject()
  1666. # 尝试从Redis中获取数据
  1667. version_info = redis.get_data(version_key)
  1668. if version_info:
  1669. # 如果在Redis中找到了数据,删除缓存
  1670. redis.del_data(version_key)
  1671. device_version_info_qs.delete()
  1672. return response.json(0)
  1673. @classmethod
  1674. def sync_device_version(cls, request_dict, response):
  1675. """
  1676. 同步设备版本信息
  1677. @param user_id: 用户ID
  1678. @param request: 请求对象
  1679. @param request_dict: 请求参数
  1680. @param response: 响应对象
  1681. @return: 响应结果
  1682. """
  1683. try:
  1684. # 从请求字典中获取设备码和版本号
  1685. version = request_dict.get('softwareVer')
  1686. d_code = request_dict.get('dCode')
  1687. # 查询设备版本配置
  1688. version_config_qs = DeviceVersionInfo.objects.filter(
  1689. d_code=d_code,
  1690. software_ver=version
  1691. )
  1692. # 检查是否存在匹配的配置
  1693. if not version_config_qs.exists():
  1694. return response.json(173) # 设备版本配置不存在
  1695. # 获取第一条匹配的记录(通常应该只有一条)
  1696. version_config = version_config_qs.first()
  1697. # 直接使用数据库字段,不需要json.loads
  1698. other_features = ''
  1699. if version_config.other_features:
  1700. other_features = json.dumps(version_config.other_features)
  1701. # 将数据库字段映射为驼峰命名的响应数据
  1702. req_data = {
  1703. 'dCode': version_config.d_code,
  1704. 'softwareVer': version_config.software_ver,
  1705. 'firmwareVer': version_config.firmware_ver,
  1706. 'videoCode': version_config.video_code,
  1707. 'regionAlexa': version_config.region_alexa,
  1708. # 布尔字段转换为int
  1709. 'supportsHumanTracking': int(version_config.supports_human_tracking),
  1710. 'supportsCustomVoice': int(version_config.supports_custom_voice),
  1711. 'supportsDualBandWifi': int(version_config.supports_dual_band_wifi),
  1712. 'supportsFourPoint': int(version_config.supports_four_point),
  1713. 'supports4g': int(version_config.supports_4g),
  1714. 'supportsPTZ': int(version_config.supports_ptz),
  1715. 'supportsAi': int(version_config.supports_ai),
  1716. 'supportsCloudStorage': int(version_config.supports_cloud_storage),
  1717. 'supportsAlexa': int(version_config.supports_alexa),
  1718. # 其他非布尔字段保持不变
  1719. 'deviceType': version_config.device_type,
  1720. 'resolution': version_config.resolution,
  1721. 'aiType': version_config.ai_type,
  1722. 'supportsAlarm': version_config.supports_alarm,
  1723. 'supportsNightVision': version_config.supports_night_vision,
  1724. 'screenChannels': version_config.screen_channels,
  1725. 'networkType': version_config.network_type,
  1726. 'otherFeatures': other_features,
  1727. 'electricityStatistics': version_config.electricity_statistics,
  1728. 'supportsPetTracking': version_config.supports_pet_tracking
  1729. }
  1730. config_thread = threading.Thread(target=DeviceManagement.sync_device_version_config, kwargs=req_data)
  1731. config_thread.start()
  1732. # 返回成功响应,包含设备版本配置信息
  1733. return response.json(0)
  1734. except Exception as e:
  1735. # 通用异常处理(建议替换为具体异常类型)
  1736. LOGGER.exception("同步设备配置失败")
  1737. return response.json(500, f'Server error: {str(e)}')
  1738. @staticmethod
  1739. def sync_device_version_config(**req_data):
  1740. """
  1741. 同步设备版本信息到本地数据库及外部服务器(含异常跳过逻辑)
  1742. """
  1743. try:
  1744. target_servers = []
  1745. if CONFIG_INFO == CONFIG_TEST:
  1746. target_servers = [
  1747. "https://www.zositechc.cn/open/device/configuration/syncVerConfig",
  1748. "https://www.dvema.com/open/device/configuration/syncVerConfig",
  1749. "https://api.zositeche.com/open/device/configuration/syncVerConfig"
  1750. ]
  1751. elif CONFIG_INFO == CONFIG_CN:
  1752. target_servers = [
  1753. "https://test.zositechc.cn/open/device/configuration/syncVerConfig",
  1754. "https://www.dvema.com/open/device/configuration/syncVerConfig",
  1755. "https://api.zositeche.com/open/device/configuration/syncVerConfig"
  1756. ]
  1757. elif CONFIG_INFO == CONFIG_US:
  1758. target_servers = [
  1759. "https://test.zositechc.cn/open/device/configuration/syncVerConfig",
  1760. "https://www.zositechc.cn/open/device/configuration/syncVerConfig",
  1761. "https://api.zositeche.com/open/device/configuration/syncVerConfig"
  1762. ]
  1763. elif CONFIG_INFO == CONFIG_EUR:
  1764. target_servers = [
  1765. "https://test.zositechc.cn/open/device/configuration/syncVerConfig",
  1766. "https://www.zositechc.cn/open/device/configuration/syncVerConfig",
  1767. "https://www.dvema.com/open/device/configuration/syncVerConfig"
  1768. ]
  1769. for server_url in target_servers:
  1770. try:
  1771. # 发送请求并设置超时(10秒)
  1772. resp = requests.post(
  1773. url=server_url,
  1774. data=req_data,
  1775. timeout=10 # 超时时间
  1776. )
  1777. resp.raise_for_status() # 抛出HTTP错误(如400/500)
  1778. LOGGER.info(f"[{server_url}] 同步成功,响应:{resp.json()}")
  1779. except requests.exceptions.ConnectTimeout:
  1780. LOGGER.error(f"[{server_url}] 连接超时,跳过")
  1781. continue
  1782. except requests.exceptions.ReadTimeout:
  1783. LOGGER.error(f"[{server_url}] 读取超时,跳过")
  1784. continue
  1785. except requests.exceptions.RequestException as e:
  1786. LOGGER.error(f"[{server_url}] 同步失败:{str(e)}")
  1787. continue # 跳过当前服务器
  1788. return True
  1789. except Exception as e:
  1790. LOGGER.exception("同步设备版本信息失败error{}".format(repr(e)))
  1791. return False
  1792. @staticmethod
  1793. def get_device_voice(request_dict, response):
  1794. """
  1795. 获取设备音频
  1796. @param request_dict:
  1797. @param response:
  1798. @return:
  1799. """
  1800. title = request_dict.get('title', None)
  1801. voice_type = request_dict.get('voiceType', None)
  1802. classification = request_dict.get('classification', None)
  1803. uid = request_dict.get('uid', None)
  1804. algorithm_type = request_dict.get('algorithmType', None)
  1805. status = request_dict.get('status', None)
  1806. page = request_dict.get('page', 1)
  1807. page_size = request_dict.get('pageSize', 20)
  1808. try:
  1809. voice_prompt_qs = VoicePromptModel.objects.all()
  1810. if title:
  1811. voice_prompt_qs = voice_prompt_qs.filter(title__icontains=title)
  1812. if voice_type:
  1813. voice_prompt_qs = voice_prompt_qs.filter(type=voice_type)
  1814. if classification:
  1815. voice_prompt_qs = voice_prompt_qs.filter(classification=classification)
  1816. if uid:
  1817. voice_prompt_qs = voice_prompt_qs.filter(uid=uid)
  1818. if algorithm_type:
  1819. voice_prompt_qs = voice_prompt_qs.filter(algorithm_type=algorithm_type)
  1820. if status:
  1821. voice_prompt_qs = voice_prompt_qs.filter(status=status)
  1822. # 分页
  1823. paginator = Paginator(voice_prompt_qs.order_by("-add_time"), page_size) # 每页显示 page_size 条
  1824. voice_prompt_page = paginator.get_page(page) # 获取当前页的数据
  1825. # 上传文件到阿里云OSS
  1826. auth = oss2.Auth(OSS_STS_ACCESS_KEY, OSS_STS_ACCESS_SECRET)
  1827. bucket = oss2.Bucket(auth, 'https://oss-cn-shenzhen.aliyuncs.com', 'ansjer-static-resources')
  1828. voice_prompt_list = []
  1829. for voice_prompt in voice_prompt_page:
  1830. filename = voice_prompt.filename
  1831. obj = 'voice_prompt/system/' + filename
  1832. filename_url = bucket.sign_url('GET', obj, 3600)
  1833. voice_prompt_list.append({
  1834. "id": voice_prompt.id,
  1835. "title": voice_prompt.title,
  1836. "type": voice_prompt.type,
  1837. "classification": voice_prompt.classification,
  1838. "filename": filename,
  1839. "filenameUrl": filename_url,
  1840. "language": voice_prompt.language,
  1841. "status": voice_prompt.status,
  1842. "addTime": voice_prompt.add_time,
  1843. "algorithmType": voice_prompt.algorithm_type,
  1844. "uid": voice_prompt.uid,
  1845. "device_types": voice_prompt.device_types
  1846. })
  1847. return response.json(0, {'list': voice_prompt_list, 'total': paginator.count})
  1848. except Exception as e:
  1849. print(e)
  1850. return response.json(500, 'error_line:{}, error_msg:{}'.format(e.__traceback__.tb_lineno, repr(e)))
  1851. @staticmethod
  1852. def algorithm_type_list(response):
  1853. """
  1854. 算法类型列表
  1855. @param response:
  1856. @return:
  1857. """
  1858. try:
  1859. device_algorithm_explain_qs = DeviceAlgorithmExplain.objects.filter(lang='cn').values('title', 'algorithm_type__type')
  1860. device_algorithm_explain = list(device_algorithm_explain_qs)
  1861. for item in device_algorithm_explain:
  1862. item['algorithm_type_id'] = item.pop('algorithm_type__type')
  1863. device_algorithm_explain.append({"title": "无", "algorithm_type_id": 99})
  1864. return response.json(0, device_algorithm_explain)
  1865. except Exception as e:
  1866. print(e)
  1867. return response.json(500, 'error_line:{}, error_msg:{}'.format(e.__traceback__.tb_lineno, repr(e)))
  1868. @staticmethod
  1869. def add_device_voice(request, request_dict, response):
  1870. """
  1871. 添加设备音频
  1872. @param request
  1873. @param request_dict:
  1874. @param response:
  1875. @return:
  1876. """
  1877. title = request_dict.get('title', None)
  1878. voice_type = request_dict.get('voiceType', None)
  1879. classification = request_dict.get('classification', None)
  1880. algorithm_type = request_dict.get('algorithmType', None)
  1881. status = request_dict.get('status', None)
  1882. language = request_dict.get('language', None)
  1883. uid = request_dict.get('uid', None)
  1884. channel = request_dict.get('channel', 1)
  1885. device_types = request_dict.get('deviceTypes', None)
  1886. voice_file = request.FILES.get('voiceFile', None)
  1887. if not all([title, voice_type, classification, algorithm_type, status, language, voice_file]):
  1888. return response.json(444)
  1889. try:
  1890. if device_types:
  1891. device_type_list = device_types.split(',')
  1892. device_type_list = list(map(int, device_type_list))
  1893. else:
  1894. device_type_list = []
  1895. classification = int(classification)
  1896. auth = oss2.Auth(OSS_STS_ACCESS_KEY, OSS_STS_ACCESS_SECRET)
  1897. bucket = oss2.Bucket(auth, 'oss-cn-shenzhen.aliyuncs.com', 'ansjer-static-resources')
  1898. file_name = voice_file.name
  1899. file_extension = os.path.splitext(file_name)[1]
  1900. filename = CommonService.createOrderID() + file_extension
  1901. voice_prompt_dict = {
  1902. "title": title,
  1903. "type": voice_type,
  1904. "classification": classification,
  1905. "filename": filename,
  1906. "language": language,
  1907. "status": status,
  1908. "algorithm_type": algorithm_type,
  1909. "add_time": int(time.time()),
  1910. "device_types": device_type_list
  1911. }
  1912. if uid and classification == 1:
  1913. voice_prompt_dict["uid"] = uid
  1914. obj = 'voice_prompt/{uid}/{channel}/'.format(uid=uid, channel=channel) + filename
  1915. bucket.put_object(obj, voice_file)
  1916. elif uid and classification == 0:
  1917. return response.json(178)
  1918. else:
  1919. obj = 'voice_prompt/system/' + filename
  1920. bucket.put_object(obj, voice_file)
  1921. VoicePromptModel.objects.create(**voice_prompt_dict)
  1922. return response.json(0)
  1923. except Exception as e:
  1924. print(e)
  1925. return response.json(500, 'error_line:{}, error_msg:{}'.format(e.__traceback__.tb_lineno, repr(e)))
  1926. @staticmethod
  1927. def edit_device_voice(request_dict, response):
  1928. """
  1929. 添加设备音频
  1930. @param request:
  1931. @param request_dict:
  1932. @param response:
  1933. @return:
  1934. """
  1935. device_voice_id = request_dict.get('deviceVoiceId', None)
  1936. title = request_dict.get('title', None)
  1937. voice_type = request_dict.get('voiceType', None)
  1938. classification = request_dict.get('classification', None)
  1939. algorithm_type = request_dict.get('algorithmType', None)
  1940. status = request_dict.get('status', None)
  1941. language = request_dict.get('language', None)
  1942. device_types = request_dict.get('deviceTypes', "")
  1943. try:
  1944. voice_prompt = VoicePromptModel.objects.get(pk=device_voice_id)
  1945. if title:
  1946. voice_prompt.title = title
  1947. if voice_type:
  1948. voice_prompt.type = voice_type
  1949. if classification:
  1950. voice_prompt.classification = classification
  1951. if algorithm_type:
  1952. voice_prompt.algorithm_type = algorithm_type
  1953. if status:
  1954. voice_prompt.status = status
  1955. if language:
  1956. voice_prompt.language = language
  1957. if device_types:
  1958. device_type_list = device_types.split(',')
  1959. device_type_list = list(map(int, device_type_list))
  1960. voice_prompt.device_types = device_type_list
  1961. voice_prompt.save()
  1962. return response.json(0)
  1963. except Exception as e:
  1964. print(e)
  1965. return response.json(500, 'error_line:{}, error_msg:{}'.format(e.__traceback__.tb_lineno, repr(e)))
  1966. @staticmethod
  1967. def del_device_voice(request_dict, response):
  1968. """
  1969. 删除设备音频
  1970. @param request_dict:
  1971. @param response:
  1972. @return:
  1973. """
  1974. device_voice_id = request_dict.get('deviceVoiceId', None)
  1975. try:
  1976. voice_prompt_qs = VoicePromptModel.objects.filter(id=device_voice_id)
  1977. filename = voice_prompt_qs[0].filename
  1978. classification = voice_prompt_qs[0].classification
  1979. uid = voice_prompt_qs[0].uid
  1980. channel = voice_prompt_qs[0].channel
  1981. auth = oss2.Auth(OSS_STS_ACCESS_KEY, OSS_STS_ACCESS_SECRET)
  1982. bucket = oss2.Bucket(auth, 'oss-cn-shenzhen.aliyuncs.com', 'ansjer-static-resources')
  1983. if classification == 1 and uid:
  1984. obj = 'voice_prompt/{uid}/{channel}/'.format(uid=uid, channel=channel) + filename
  1985. bucket.delete_object(obj)
  1986. else:
  1987. obj = 'voice_prompt/system/' + filename
  1988. bucket.delete_object(obj)
  1989. voice_prompt_qs.delete()
  1990. return response.json(0)
  1991. except Exception as e:
  1992. print(e)
  1993. return response.json(500, 'error_line:{}, error_msg:{}'.format(e.__traceback__.tb_lineno, repr(e)))
  1994. @staticmethod
  1995. def device_type_list(response):
  1996. """
  1997. 获取设备类型
  1998. @param response:
  1999. @return:
  2000. """
  2001. try:
  2002. subquery = DeviceTypeModel.objects.filter(
  2003. type=OuterRef('type')
  2004. ).values('type').annotate(
  2005. min_id=Min('id')
  2006. ).values('min_id')
  2007. # 根据最小 id 获取对应的 name 和 type
  2008. device_type_qs = DeviceTypeModel.objects.filter(
  2009. id__in=Subquery(subquery)
  2010. ).values("name", "type")
  2011. return response.json(0, list(device_type_qs))
  2012. except Exception as e:
  2013. print(e)
  2014. return response.json(500, 'error_line:{}, error_msg:{}'.format(e.__traceback__.tb_lineno, repr(e)))
  2015. @staticmethod
  2016. def get_baidu_big_model_license(request_dict, response):
  2017. """查询百度大模型许可证列表"""
  2018. page_no = request_dict.get('pageNo')
  2019. page_size = request_dict.get('pageSize')
  2020. serial = request_dict.get('serial', '')
  2021. license_name = request_dict.get('licenseName', '')
  2022. use_status = request_dict.get('useStatus')
  2023. if not all([page_no, page_size]):
  2024. return response.json(444)
  2025. try:
  2026. query = BaiduBigModelLicense.objects.all()
  2027. if serial:
  2028. query = query.filter(serial__contains=serial)
  2029. if license_name:
  2030. query = query.filter(license_name__contains=license_name)
  2031. if use_status:
  2032. query = query.filter(use_status=use_status)
  2033. total = query.count()
  2034. licenses = query.order_by('-id')[
  2035. (int(page_no)-1)*int(page_size):int(page_no)*int(page_size)
  2036. ].values('id', 'serial', 'license_name', 'use_status', 'created_time', 'updated_time')
  2037. return response.json(0, {
  2038. 'list': list(licenses),
  2039. 'total': total
  2040. })
  2041. except Exception as e:
  2042. return response.json(500, 'error_line:{}, error_msg:{}'.format(e.__traceback__.tb_lineno, repr(e)))
  2043. @staticmethod
  2044. def add_baidu_big_model_license(request, response):
  2045. """添加百度大模型许可证"""
  2046. file = request.FILES.get('file', None)
  2047. if not file:
  2048. return response.json(444)
  2049. try:
  2050. license_name = str(file)
  2051. now_time = int(time.time())
  2052. # 上传文件到华为云OBS
  2053. obs_client = ObsClient(
  2054. access_key_id=HUAWEICLOUD_AK,
  2055. secret_access_key=HUAWEICLOUD_SK,
  2056. server=HUAWEICLOUD_OBS_SERVER
  2057. )
  2058. resp = obs_client.putObject(
  2059. bucketName=HUAWEICLOUD_BAIDU_BIG_MODEL_LICENSE_BUKET,
  2060. objectKey=license_name,
  2061. content=file
  2062. )
  2063. assert resp.status < 300
  2064. # 更新或创建数据
  2065. license_qs = BaiduBigModelLicense.objects.filter(license_name=license_name)
  2066. if license_qs.exists():
  2067. license_qs.update(updated_time=now_time)
  2068. else:
  2069. BaiduBigModelLicense.objects.create(
  2070. license_name=license_name,
  2071. created_time=now_time,
  2072. updated_time=now_time
  2073. )
  2074. return response.json(0)
  2075. except Exception as e:
  2076. return response.json(500, 'error_line:{}, error_msg:{}'.format(e.__traceback__.tb_lineno, repr(e)))
  2077. @staticmethod
  2078. def edit_baidu_big_model_license(request, request_dict, response):
  2079. """编辑百度大模型许可证"""
  2080. license_id = request_dict.get('id')
  2081. serial = request_dict.get('serial')
  2082. use_status = request_dict.get('useStatus')
  2083. if not license_id:
  2084. return response.json(444)
  2085. try:
  2086. update_data = {
  2087. 'updated_time': int(time.time())
  2088. }
  2089. if serial:
  2090. update_data['serial'] = serial
  2091. if use_status is not None:
  2092. update_data['use_status'] = int(use_status)
  2093. BaiduBigModelLicense.objects.filter(id=license_id).update(**update_data)
  2094. return response.json(0)
  2095. except Exception as e:
  2096. return response.json(500, 'error_line:{}, error_msg:{}'.format(e.__traceback__.tb_lineno, repr(e)))
  2097. @staticmethod
  2098. def del_baidu_big_model_license(request_dict, response):
  2099. """删除百度大模型许可证"""
  2100. license_id = request_dict.get('id')
  2101. if not license_id:
  2102. return response.json(444)
  2103. try:
  2104. # 先查询出license_name
  2105. baidu_license = BaiduBigModelLicense.objects.filter(id=license_id).first()
  2106. if not baidu_license:
  2107. return response.json(444)
  2108. license_name = baidu_license.license_name
  2109. # 删除数据库记录
  2110. BaiduBigModelLicense.objects.filter(id=license_id).delete()
  2111. # 删除华为云上的文件
  2112. obs_client = ObsClient(
  2113. access_key_id=HUAWEICLOUD_AK,
  2114. secret_access_key=HUAWEICLOUD_SK,
  2115. server=HUAWEICLOUD_OBS_SERVER
  2116. )
  2117. obs_client.deleteObject(
  2118. bucketName=HUAWEICLOUD_BAIDU_BIG_MODEL_LICENSE_BUKET,
  2119. objectKey=license_name
  2120. )
  2121. return response.json(0)
  2122. except Exception as e:
  2123. return response.json(500, 'error_line:{}, error_msg:{}'.format(e.__traceback__.tb_lineno, repr(e)))
  2124. @staticmethod
  2125. def get_instavision(request_dict, response):
  2126. """查询即时视觉列表"""
  2127. page_no = request_dict.get('pageNo')
  2128. page_size = request_dict.get('pageSize')
  2129. device_id = request_dict.get('deviceId', '')
  2130. mac = request_dict.get('mac', '')
  2131. access_key = request_dict.get('accessKey', '')
  2132. use_status = request_dict.get('useStatus')
  2133. if not all([page_no, page_size]):
  2134. return response.json(444)
  2135. try:
  2136. query = Instavision.objects.all()
  2137. if device_id:
  2138. query = query.filter(device_id__contains=device_id)
  2139. if mac:
  2140. query = query.filter(mac__contains=mac)
  2141. if access_key:
  2142. query = query.filter(access_key__contains=access_key)
  2143. if use_status is not None:
  2144. query = query.filter(use_status=use_status)
  2145. total = query.count()
  2146. instavisions = query.order_by('-id')[
  2147. (int(page_no)-1)*int(page_size):int(page_no)*int(page_size)
  2148. ].values('id', 'mac', 'device_id', 'access_key', 'use_status', 'created_time', 'updated_time')
  2149. return response.json(0, {
  2150. 'list': list(instavisions),
  2151. 'total': total
  2152. })
  2153. except Exception as e:
  2154. return response.json(500, 'error_line:{}, error_msg:{}'.format(e.__traceback__.tb_lineno, repr(e)))
  2155. @staticmethod
  2156. def add_instavision(request, response):
  2157. """添加即时视觉
  2158. 仅支持CSV批量导入
  2159. """
  2160. file = request.FILES.get('file', None)
  2161. if not file:
  2162. return response.json(444, '请上传CSV文件')
  2163. try:
  2164. # 读取CSV文件内容
  2165. csv_content = io.StringIO(file.read().decode('utf-8'))
  2166. csv_reader = csv.DictReader(csv_content)
  2167. now_time = int(time.time())
  2168. # 获取所有已存在的device_id
  2169. existing_device_ids = set(Instavision.objects.values_list('device_id', flat=True))
  2170. # 准备批量创建的对象列表
  2171. instavision_objects = []
  2172. for row in csv_reader:
  2173. # 获取Device Id和Access Key列的数据
  2174. device_id = row.get('Device Id', '')
  2175. access_key = row.get('Access Key', '')
  2176. if not device_id or not access_key:
  2177. continue
  2178. # 检查是否已存在相同的device_id
  2179. if device_id in existing_device_ids:
  2180. continue
  2181. # 添加到待创建列表
  2182. instavision_objects.append(Instavision(
  2183. device_id=device_id,
  2184. access_key=access_key,
  2185. created_time=now_time,
  2186. updated_time=now_time
  2187. ))
  2188. # 将此device_id添加到已存在集合中,防止CSV中有重复
  2189. existing_device_ids.add(device_id)
  2190. # 使用bulk_create批量创建记录
  2191. if instavision_objects:
  2192. Instavision.objects.bulk_create(instavision_objects)
  2193. return response.json(0)
  2194. except Exception as e:
  2195. return response.json(500, 'error_line:{}, error_msg:{}'.format(e.__traceback__.tb_lineno, repr(e)))
  2196. @staticmethod
  2197. def edit_instavision(request_dict, response):
  2198. """编辑即时视觉"""
  2199. instavision_id = request_dict.get('id')
  2200. device_id = request_dict.get('deviceId')
  2201. access_key = request_dict.get('accessKey')
  2202. mac = request_dict.get('mac')
  2203. use_status = request_dict.get('useStatus')
  2204. if not instavision_id:
  2205. return response.json(444)
  2206. try:
  2207. update_data = {
  2208. 'updated_time': int(time.time())
  2209. }
  2210. if device_id:
  2211. # 检查是否与其他记录的device_id冲突
  2212. if Instavision.objects.exclude(id=instavision_id).filter(device_id=device_id).exists():
  2213. return response.json(444, '设备ID已存在')
  2214. update_data['device_id'] = device_id
  2215. if access_key:
  2216. update_data['access_key'] = access_key
  2217. if mac:
  2218. update_data['mac'] = mac
  2219. if use_status is not None:
  2220. update_data['use_status'] = int(use_status)
  2221. Instavision.objects.filter(id=instavision_id).update(**update_data)
  2222. return response.json(0)
  2223. except Exception as e:
  2224. return response.json(500, 'error_line:{}, error_msg:{}'.format(e.__traceback__.tb_lineno, repr(e)))
  2225. @staticmethod
  2226. def del_instavision(request_dict, response):
  2227. """删除即时视觉"""
  2228. instavision_id = request_dict.get('id')
  2229. if not instavision_id:
  2230. return response.json(444)
  2231. try:
  2232. # 删除数据库记录
  2233. Instavision.objects.filter(id=instavision_id).delete()
  2234. return response.json(0)
  2235. except Exception as e:
  2236. return response.json(500, 'error_line:{}, error_msg:{}'.format(e.__traceback__.tb_lineno, repr(e)))
  2237. @staticmethod
  2238. def device_power_display(request_dict, response):
  2239. """
  2240. 获取设备电量显示
  2241. @param request_dict: 包含查询参数的字典
  2242. @param response: 响应对象
  2243. @return: 分页后的设备日报数据,包含聚合信息(如果条件满足)
  2244. """
  2245. device_id = request_dict.get('deviceId', None)
  2246. start_time = request_dict.get('startTime', None)
  2247. end_time = request_dict.get('endTime', None)
  2248. page = int(request_dict.get('page', 1)) # 默认第1页
  2249. page_size = int(request_dict.get('pageSize', 10)) # 默认每页10条
  2250. device_daily_report_qs = DeviceDailyReport.objects.filter(type=1)
  2251. # 应用过滤条件
  2252. if device_id:
  2253. device_daily_report_qs = device_daily_report_qs.filter(device_id=device_id)
  2254. device_daily_report_qs = device_daily_report_qs.filter(report_time__gt=0)
  2255. if start_time and end_time:
  2256. start_time = int(start_time)
  2257. end_time = int(end_time)
  2258. device_daily_report_qs = device_daily_report_qs.filter(
  2259. report_time__gte=start_time,
  2260. report_time__lte=end_time
  2261. )
  2262. # 计算总数(用于分页)
  2263. total_count = device_daily_report_qs.count()
  2264. device_daily_report_qs = device_daily_report_qs.order_by('-report_time')
  2265. # 应用分页
  2266. paginator = Paginator(device_daily_report_qs, page_size)
  2267. device_daily_report_page = paginator.page(page)
  2268. # 序列化分页数据
  2269. device_daily_report = list(device_daily_report_page.object_list.values(
  2270. 'device_id',
  2271. 'battery_level',
  2272. 'report_time',
  2273. 'human_detection',
  2274. 'working_hours',
  2275. 'wake_sleep',
  2276. 'pir_wakeup_count',
  2277. 'mqtt_wakeup_count'
  2278. ))
  2279. # 构建返回数据
  2280. data = {
  2281. "list": device_daily_report,
  2282. "total": total_count,
  2283. }
  2284. # 如果满足条件(有设备ID和时间范围),计算聚合数据
  2285. if device_id and start_time and end_time:
  2286. aggregates = device_daily_report_qs.aggregate(
  2287. total_human_detection=Sum('human_detection'),
  2288. total_working_hours=Sum('working_hours'),
  2289. total_wake_sleep=Sum('wake_sleep')
  2290. )
  2291. data['data_statistics'] = {
  2292. 'total_human_detection': aggregates.get('total_human_detection', 0),
  2293. 'total_working_hours': aggregates.get('total_working_hours', 0),
  2294. 'total_wake_sleep': aggregates.get('total_wake_sleep', 0)
  2295. }
  2296. return response.json(0, data)