camera_manage.py 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421
  1. import re
  2. import requests
  3. import time
  4. import ast
  5. from django.conf import settings
  6. from django.db.models import Count
  7. from django.core.paginator import Paginator
  8. from django.db import transaction
  9. from smartfarming.api.views.forecast.all_dict import insect_dict, attract_discern
  10. from smartfarming.models.sim_card import MongoMsg_Conf
  11. from smartfarming.models.device import MongoDevice
  12. from smartfarming.models.camera import MongoCameraPhoto, MongoCameraData, MongoCameraAccount
  13. from smartfarming.serializers.device_serializers import DeviceSerializers
  14. from smartfarming.utils import controlMove
  15. from smartfarming.utils import bindDeviceLive, getLive
  16. from kedong.decoration import kedong_deco, PortError
  17. config_dict = settings.CONFIG
  18. @kedong_deco(login_required=True)
  19. def list_camera(request):
  20. """
  21. 获取监控设备列表 :
  22. 参数:
  23. page 非必传(num) 页码,默认为1
  24. device_id 非必传 设备ID, 不传为监控列表, 传设备号为搜索
  25. page_size 非必传 一页条数,默认为10
  26. 返回值:
  27. {
  28. "data": {
  29. data : {
  30. "device_name":"", 设备名称
  31. "device_id":"", 设备ID
  32. "photo_num":"", 是否拍过照片 0未拍过 1拍过
  33. "status":"", 设备状态 0离线 1在线
  34. "camera_playback":"" 用来判断是否有录像功能 0不支持 1支持
  35. "sim":"" 监控SIM 卡
  36. }
  37. counts : 99 总数
  38. }
  39. "errorCode": 0,
  40. "message": "",
  41. "formError": {}
  42. }
  43. """
  44. _list = []
  45. myuser = request.myuser
  46. post_info = request.POST
  47. device_id = post_info.get('device_id')
  48. page = int(post_info.get('page', 1))
  49. page_size = int(post_info.get('page_size', 10))
  50. search_dict = {
  51. "device_type_id": 6
  52. }
  53. if device_id:
  54. search_dict["device_id"] = re.compile(fr"^.*{device_id}.*$")
  55. # total_num, data_list = MongoDevice.get_device_list(myuser, match=search_dict, page_num=page, page_size=page_size)
  56. queryset = MongoDevice.objects.filter(device_type_id=6).order_by("-uptime")
  57. total_num = queryset.count()
  58. paginator = Paginator(queryset, page_size)
  59. page_obj = paginator.get_page(page)
  60. serializers = DeviceSerializers(page_obj, many=True)
  61. data_list = serializers.data
  62. _list = []
  63. device_id_list = []
  64. for x in data_list:
  65. device_id = x.get("device_id")
  66. device_id_list.append(device_id)
  67. _list.append({
  68. "device_name": x.get("device_name"),
  69. "device_id": device_id,
  70. "photo_num": "",
  71. "status": x.get("device_status"),
  72. "camera_playback": "",
  73. "sim": x.get("simid")
  74. })
  75. photo_queryset = MongoCameraPhoto.objects.filter(device_id__in=device_id_list, photo_status=1).values('device_id').annotate(count=Count('device_id'))
  76. phote_dict = {p['device_id']: "1" for p in photo_queryset}
  77. playback_dict = {y['device_id']: y["camera_playback"] for y in MongoCameraData.objects.filter(device_id__in=device_id_list).values('device_id','camera_playback')}
  78. for item in _list:
  79. item["photo_num"] = phote_dict.get(device_id, "0")
  80. item["camera_playback"] = playback_dict.get(device_id,"0")
  81. datas = {"data": _list, "counts": total_num}
  82. return datas
  83. @kedong_deco(login_required=True)
  84. def addr_camera_list(request):
  85. """
  86. 获取监控设备播放地址
  87. 参数:
  88. device_id 必传 (string) 监控设备的序列号
  89. 返回值:
  90. {
  91. "data": {
  92. "hls": "http://test.ys7.com:66/openlive/b475942b03544a5aa35b651670d8712c.m3u8", HLS流畅直播地址
  93. "hlsHd": "http://test.ys7.com:66/openlive/b475942b03544a5aa35b651670d8712c.hd.m3u8", HLS高清直播地址
  94. "rtmp": "rtmp://10.82.0.190:1935/openlive/b475942b03544a5aa35b651670d8712c", RTMP流畅直播地址
  95. "rtmpHd": "rtmp://10.82.0.190:1935/openlive/b475942b03544a5aa35b651670d8712c.hd" RTMP高清直播地址
  96. }
  97. "errorCode": 0,
  98. "message": "",
  99. "formError": {}
  100. }
  101. """
  102. try:
  103. if 'HTTP_X_FORWARDED_FOR' in request.META:
  104. ip = request.META['HTTP_X_FORWARDED_FOR']
  105. else:
  106. ip = request.META['HTTP_X_REAL_IP']
  107. except Exception as KeyError:
  108. ip = request.META['REMOTE_ADDR']
  109. device_id = request.POST.get('device_id')
  110. # try:
  111. # ic = InterfaceCallLog()
  112. # ic.ip = ip
  113. # ic.device_id = device_id
  114. # ic.interface = "addr_camera_list"
  115. # ic.meta = str(request.META)
  116. # ic.save()
  117. # except Exception as e:
  118. # pass
  119. # if device_id in jk_list.keys():
  120. # if redis_pool.get(device_id):
  121. # url_path = redis_pool.get(device_id)
  122. # else:
  123. # cameraIndexCode = jk_list.get(device_id,"")
  124. # url = "http://223.151.55.58:8082/zhcg-serve/hkVideo/api/getPreviewURLsByHls?cameraIndexCode={}&streamType=0".format(cameraIndexCode)
  125. # try:
  126. # url_path = (requests.get(url,timeout=5).json())["data"]["url"]
  127. # except:
  128. # url_path = ""
  129. # # 设置播放地址到期时间5分钟
  130. # redis_pool.set(device_id,url_path,300)
  131. # # 因为其他设备返回的数值是字符串的,所以进行拼接
  132. # data = "{'hls':'%s','hlsHd':'%s','rtmp':'%s','rtmpHd':'%s'}"%(url_path,url_path,url_path,url_path)
  133. # return data
  134. try:
  135. addr = MongoCameraData.objects.get(device_id=device_id).device_info
  136. except:
  137. addr = {}
  138. return addr
  139. @kedong_deco(login_required=True)
  140. def ctrl_camera(request):
  141. """
  142. 控制监控设备转动 :
  143. 参数:
  144. device_id 必传 (string) 监控设备的序列号
  145. ctrl 必传 (string) 操作指令 move 控制球机转动 stop 停止球机转动
  146. movenum ctrl=move时必传(string) 0-上,1-下,2-左,3-右,8-放大,9-缩小
  147. 返回值:
  148. {
  149. "data": success, success成功 default失败
  150. "errorCode": 0,
  151. "message": "",
  152. "formError": {}
  153. }
  154. """
  155. device_id = request.POST.get('device_id')
  156. ctrl = request.POST.get('ctrl')
  157. account_id = MongoCameraData.objects.filter(device_id=device_id).first()
  158. if not account_id:
  159. raise PortError("","未找到此设备")
  160. camera_query = MongoCameraAccount.objects.filter(id=int(account_id.account_id)).first()
  161. if not camera_query:
  162. raise PortError("","未找到此账号")
  163. channelNo = "1"
  164. if device_id.find("-") != -1:
  165. channelNo = device_id.split("-")[1]
  166. device_id = device_id.split("-")[0]
  167. # 操作命令:0-上,1-下,2-左,3-右,4-左上,5-左下,6-右上,7-右下,8-放大,9-缩小,10-近焦距,11-远焦距
  168. if ctrl == "move":
  169. dire = request.POST.get('movenum')
  170. # 增加大华相机操作功能
  171. if camera_query.account_type == 1:
  172. if dire not in ("0","1","2","3","8","9"):
  173. raise PortError("movenum","暂不支持其它指令")
  174. appId = camera_query.app_key
  175. appSecret = camera_query.app_secret
  176. controlMove(appId,appSecret,device_id,dire,channelNo)
  177. else:
  178. accessToken = camera_query.token
  179. ctrl_url = 'https://open.ys7.com/api/lapp/device/ptz/start'
  180. speed = '1'
  181. data = {'accessToken':accessToken, 'deviceSerial':device_id, 'channelNo':channelNo, 'speed':speed, 'direction':dire}
  182. res1 = requests.post(ctrl_url,data=data)
  183. elif ctrl == "stop":
  184. time.sleep(0.4)
  185. # 增加大华相机操作功能
  186. if camera_query.account_type == 1:
  187. dire = "10"
  188. appId = camera_query.app_key
  189. appSecret = camera_query.app_secret
  190. controlMove(appId,appSecret,device_id,dire,channelNo)
  191. else:
  192. accessToken = camera_query.token
  193. ctrl_url = 'https://open.ys7.com/api/lapp/device/ptz/stop'
  194. data = {'accessToken':accessToken, 'deviceSerial':device_id, 'channelNo':channelNo}
  195. res2 = requests.post(ctrl_url,data=data)
  196. return True
  197. @kedong_deco(login_required=False)
  198. def see_camera_account(request):
  199. """
  200. 查看当前绑定的萤石云账号信息\按业务员名字搜索\萤石云账号搜索
  201. 参数:
  202. account 非必传(str) 按萤石云账号名字搜索
  203. salesman 非必传(str) 按业务员名字搜索
  204. 说明:两个参数都不传为所有数据,不进行筛选操作
  205. 返回值:
  206. {
  207. "errorCode": 0,
  208. "message": "",
  209. "formError": {},
  210. "data": [
  211. {
  212. "id": 1, 萤石云账号id
  213. "account": "hnyf" 萤石云名称
  214. }
  215. ],
  216. "params": {}
  217. }
  218. """
  219. account = request.POST.get("account")
  220. salesman = request.POST.get("salesman")
  221. camera_query = MongoCameraAccount.objects.all().order_by("-id")
  222. if account:
  223. camera_query = camera_query.filter(account__icontains=account)
  224. if salesman:
  225. camera_query = camera_query.filter(salesman__icontains=salesman)
  226. data = [{'id':i.id,'account':i.account} for i in camera_query]
  227. return data
  228. @kedong_deco(login_required=True)
  229. def add_camera_account(request):
  230. """
  231. 添加萤石云账号
  232. 管理员可操作
  233. 参数:
  234. account 必传(str) 萤石云账号
  235. salesman 必传(str) 萤石云账号所相关的业务员名称
  236. app_token 必传(str) 萤石云账号 token
  237. app_key 必传(str) 萤石云账号 appkey
  238. app_secret 必传(str) 萤石云账号 appsecret
  239. 2022-08-19 08:54 csx
  240. 增加监控账户区分,在不影响原来的功能上进行修改,增加大华乐橙云账号添加
  241. account_type 非必传(number) 监控设备类型 0代表海康 1代表大华,默认是0
  242. """
  243. account = request.POST.get("account")
  244. salesman = request.POST.get("salesman")
  245. token = request.POST.get("app_token")
  246. app_key = request.POST.get("app_key")
  247. app_secret = request.POST.get("app_secret")
  248. account_type = request.POST.get("account_type","0")
  249. if account_type not in ("0","1"):
  250. raise PortError("","无法识别此监控账号类型")
  251. if not all([account,salesman,token,app_key,app_secret]):
  252. raise PortError("","请把参数填写完整")
  253. now_time = int(time.time())
  254. camera_query = MongoCameraAccount.objects.filter(app_key=app_key,account_type=account_type).first()
  255. if camera_query:
  256. raise PortError("","此appkey已存在,请勿重复添加")
  257. try:
  258. MongoCameraAccount.objects.create(account=account,salesman=salesman,token=token,addtime=now_time,uptime=now_time,
  259. app_key=app_key,app_secret=app_secret,account_type=account_type)
  260. except:
  261. raise PortError("","添加萤石账号失败")
  262. return True
  263. @transaction.atomic
  264. @kedong_deco(login_required=True)
  265. def add_camera(request):
  266. """
  267. 添加监控设备接口:
  268. 参数:
  269. device_id 必传 (string) 监控设备的序列号
  270. camera_channel 必传 (string) 监控通道号
  271. camera_playback 必传 (string) 是否支持回放功能,0不支持 1支持
  272. 新加参数
  273. account_id 必传 (string) 萤石云账号id
  274. 2022-08-19 08:54 csx
  275. 增加监控账户区分,在不影响原来的功能上进行修改,增加大华乐橙云监控绑定
  276. 返回值:
  277. {
  278. "data": null,
  279. "errorCode": 0,
  280. "message": ,
  281. "formError": {}
  282. }
  283. """
  284. device_id = request.POST.get('device_id')
  285. camera_channel = request.POST.get("camera_channel","0")
  286. camera_playback = request.POST.get("camera_playback","0")
  287. account_id = request.POST.get("account_id",1)
  288. if not account_id.isdigit():
  289. raise PortError("account_id","无效参数")
  290. if not device_id:
  291. raise PortError("device_id","未传设备号")
  292. if not camera_channel.isdigit():
  293. raise PortError("camera_channel","无效参数")
  294. if camera_playback not in ("0","1"):
  295. raise PortError("camera_playback","参数超出范围")
  296. now_time = int(time.time())
  297. camera_query = MongoCameraAccount.objects.filter(id=int(account_id)).first()
  298. if not camera_query:
  299. raise PortError("","未找到此账号")
  300. device_ids = device_id + "-" + camera_channel
  301. # if MongoCameraData.objects.filter(device_id=device_id).exists() or MongoDevice.objects.filter(device_id=device_id).exists():
  302. # raise PortError("","设备已存在,请勿重复添加")
  303. # 使用的是大华乐橙云账号监控接入,监控通道号大华的从0开始
  304. if camera_query.account_type == 1:
  305. appId = camera_query.app_key
  306. appSecret = camera_query.app_secret
  307. device_live_data = bindDeviceLive(appId, appSecret, device_id,camera_channel)
  308. code = device_live_data["result"]["code"]
  309. if code == "0":
  310. live_path = device_live_data["result"]["data"]["streams"][0]["hls"]
  311. elif code == "LV1001":
  312. # 如直播地址已存在,则需要查询直播地址列表
  313. live_data = getLive(appId, appSecret, device_id, camera_channel)
  314. if live_data["result"]["code"] == "0":
  315. try:
  316. live_path = live_data["result"]["data"]["streams"][0]["hls"]
  317. except:
  318. raise PortError("","获取直播地址失败")
  319. else:
  320. raise PortError("",live_data)
  321. else:
  322. msg = device_live_data["result"]["msg"]
  323. raise PortError("", msg)
  324. device_info = {
  325. "hls": live_path,
  326. "hlsHd": live_path,
  327. "rtmp": live_path,
  328. "rtmpHd": live_path
  329. }
  330. else:
  331. accessToken = camera_query.token
  332. url = config_dict.get("camera").get("ys_open")
  333. data = {"accessToken":accessToken,"source":"%s:%s"%(device_id,str(camera_channel))}
  334. res = requests.post(url,data=data)
  335. if ast.literal_eval(res.text)["code"] == "200":
  336. url_1 = config_dict.get("camera").get("ys_get")
  337. res_1 = requests.post(url_1,data=data)
  338. try:
  339. addr = ast.literal_eval(res_1.text)["data"][0]
  340. device_info = {
  341. "hls": addr["hls"],
  342. "hlsHd": addr["hlsHd"],
  343. "rtmp": addr["rtmp"],
  344. "rtmpHd": addr["rtmpHd"]
  345. }
  346. except Exception as e:
  347. raise PortError("device_id", "解析结果异常")
  348. else:
  349. raise PortError("","Token过期,设备激活失败")
  350. try:
  351. # MongoDevice.objects.create(device_id=device_ids,device_type_id=6,addtime=now_time,device_code=1,uptime=now_time)
  352. MongoCameraData.objects.create(device_id=device_ids,device_info=device_info,addtime=now_time,camera_playback=camera_playback,account_id=account_id)
  353. except Exception as e:
  354. raise PortError(" ", "添加设备失败")
  355. return True