index.py 33 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797
  1. import json
  2. import logging
  3. import subprocess
  4. import time
  5. from datetime import datetime
  6. import requests
  7. from django.http import JsonResponse
  8. from django.shortcuts import render
  9. from django.views.generic import TemplateView
  10. from azoauth.config import *
  11. from model.models import UserModel, UidRtspModel, AlexaAuthModel, UserCountModel, SwitchModel
  12. from object.RedisObject import RedisObject
  13. from object.ResObject import ResObject
  14. from object.ResponseObject import ResponseObject
  15. from object.tkObject import tkObject
  16. from service.CommonService import CommonService
  17. class authView(TemplateView):
  18. def post(self, request, *args, **kwargs):
  19. request.encoding = 'utf-8'
  20. request_dict = json.loads(request.body.decode('utf-8'))
  21. return self.validate(request_dict)
  22. def get(self, request, *args, **kwargs):
  23. request.encoding = 'utf-8'
  24. request_dict = request.GET
  25. return self.validate(request_dict)
  26. def validate(self, request_dict):
  27. logger = logging.getLogger('django')
  28. logger.info('------oa2/auth请求参数: {}------'.format(request_dict))
  29. state = request_dict.get("state", '')
  30. client_id = request_dict.get("client_id", '')
  31. response_type = request_dict.get("response_type", '')
  32. scope = request_dict.get("scope", '')
  33. redirect_uri = request_dict.get("redirect_uri", '')
  34. context = {
  35. 'state': state,
  36. 'client_id': client_id,
  37. 'response_type': response_type,
  38. 'scope': scope,
  39. 'redirect_uri': redirect_uri,
  40. 'skill_name': 'zosi smart'
  41. }
  42. return render(request=None, template_name="login.html", context=context)
  43. # Anlapus登录
  44. class authAnlapusView(TemplateView):
  45. def post(self, request, *args, **kwargs):
  46. request.encoding = 'utf-8'
  47. request_dict = json.loads(request.body.decode('utf-8'))
  48. return self.validate(request_dict)
  49. def get(self, request, *args, **kwargs):
  50. request.encoding = 'utf-8'
  51. request_dict = request.GET
  52. return self.validate(request_dict)
  53. def validate(self, request_dict):
  54. state = request_dict.get("state", '')
  55. client_id = request_dict.get("client_id", '')
  56. response_type = request_dict.get("response_type", '')
  57. scope = request_dict.get("scope", '')
  58. redirect_uri = request_dict.get("redirect_uri", '')
  59. context = {
  60. 'state': state,
  61. 'client_id': client_id,
  62. 'response_type': response_type,
  63. 'scope': scope,
  64. 'redirect_uri': redirect_uri,
  65. 'skill_name': 'Anlapus'
  66. }
  67. return render(request=None, template_name="login_anlapus.html", context=context)
  68. # loocam登录
  69. class authLoocamView(TemplateView):
  70. def post(self, request, *args, **kwargs):
  71. request.encoding = 'utf-8'
  72. request_dict = json.loads(request.body.decode('utf-8'))
  73. return self.validate(request_dict)
  74. def get(self, request, *args, **kwargs):
  75. request.encoding = 'utf-8'
  76. request_dict = request.GET
  77. return self.validate(request_dict)
  78. def validate(self, request_dict):
  79. state = request_dict.get("state", '')
  80. client_id = request_dict.get("client_id", '')
  81. response_type = request_dict.get("response_type", '')
  82. scope = request_dict.get("scope", '')
  83. redirect_uri = request_dict.get("redirect_uri", '')
  84. context = {
  85. 'state': state,
  86. 'client_id': client_id,
  87. 'response_type': response_type,
  88. 'scope': scope,
  89. 'redirect_uri': redirect_uri,
  90. 'skill_name': 'loocam'
  91. }
  92. logger = logging.getLogger('django')
  93. logger.info('loocam请求登录网页,参数为{}'.format(context))
  94. return render(request=None, template_name="login_loocam.html", context=context)
  95. class loginHandleView(TemplateView):
  96. def post(self, request, *args, **kwargs):
  97. request.encoding = 'utf-8'
  98. request_dict = json.loads(request.body.decode('utf-8'))
  99. return self.validate(request_dict)
  100. def get(self, request, *args, **kwargs):
  101. request.encoding = 'utf-8'
  102. request_dict = request.GET
  103. return self.validate(request_dict)
  104. def validate(self, request_dict):
  105. response = ResObject()
  106. user = request_dict.get("user", '')
  107. pwd = request_dict.get("pwd", '')
  108. state = request_dict.get("state", '')
  109. client_id = request_dict.get("client_id", '')
  110. response_type = request_dict.get("response_type", '')
  111. scope = request_dict.get("scope", '')
  112. redirect_uri = request_dict.get("redirect_uri", '')
  113. skill_name = request_dict.get("skill_name", '')
  114. # 返回code
  115. logger = logging.getLogger('django')
  116. logger.info('------开始认证登录------')
  117. logger.info('userName: {}, userPwd: {}, redirect_uri: {}'.format(user, pwd, redirect_uri))
  118. if client_id != 'azalexaclient' or response_type != 'code' or scope != 'profile':
  119. return response.json(10, res={'msg': 'error'}, extra={'msg': 'message wrong'})
  120. # 请求美洲服登录接口
  121. region_code = 'US'
  122. auth_request_url = '{SERVER_PREFIX}/oalexa/auth'.format(SERVER_PREFIX=SERVER_PREFIX)
  123. requests_data = {'userName': user, 'userPwd': pwd}
  124. res = requests.post(url=auth_request_url, data=requests_data)
  125. if res.status_code != 200:
  126. return response.json(10, res={'错误': '请求响应异常'})
  127. res_json = res.json()
  128. logger.info('美洲服务器响应: {}'.format(res_json))
  129. # 如果result_code不为0且region_code为EU,请求欧洲服登录接口
  130. if res_json['result_code'] != 0:
  131. if res_json['result_code'] == 104 or res_json['result']['region_code'] == 'EU':
  132. auth_request_url = '{SERVER_PREFIX}/oalexa/auth'.format(SERVER_PREFIX=SERVER_PREFIX_EU)
  133. res = requests.post(url=auth_request_url, data=requests_data)
  134. if res.status_code != 200:
  135. return response.json(10, res={'错误': '请求响应异常'})
  136. res_json = res.json()
  137. logger.info('欧洲服务器响应: {}'.format(res_json))
  138. if res_json['result_code'] != 0:
  139. region_code = 'EU'
  140. if res_json['result_code'] != 0:
  141. return response.json(10, res={'msg': 'error'}, extra={'msg': res_json['reason']})
  142. nowTime = int(time.time())
  143. code = CommonService.encrypt_data(32)
  144. userID = res_json['result']['userID']
  145. user_qs = UserModel.objects.filter(userID=userID)
  146. if user_qs.exists():
  147. user_qs.update(region_code=region_code, code=code, updTime=nowTime)
  148. else:
  149. UserModel.objects.create(userID=userID, region_code=region_code, code=code, addTime=nowTime,
  150. updTime=nowTime)
  151. year_month = str(time.strftime('%Y%m', time.localtime(nowTime))) # 获取当前年月
  152. user_count_qs = UserCountModel.objects.filter(skill_name=skill_name, year_month=year_month).values('amount')
  153. if not user_count_qs.exists():
  154. UserCountModel.objects.create(skill_name=skill_name, year_month=year_month, amount=1)
  155. else:
  156. # 用户数量+1
  157. amount = user_count_qs[0]['amount'] + 1
  158. user_count_qs.update(amount=amount)
  159. redirect_uri += '?code=' + code + '&state=' + state
  160. return response.json(0, res=redirect_uri)
  161. class oa2TokenView(TemplateView):
  162. def post(self, request, *args, **kwargs):
  163. request.encoding = 'utf-8'
  164. # request_dict = json.loads(request.body.decode('utf-8'))
  165. request_dict = request.POST
  166. return self.validate(request_dict)
  167. def get(self, request, *args, **kwargs):
  168. request.encoding = 'utf-8'
  169. request_dict = request.GET
  170. return self.validate(request_dict)
  171. def validate(self, request_dict):
  172. # 增加对code和client_id的校验代码,返回access_token和refresh_token
  173. code = request_dict.get("code", None)
  174. client_id = request_dict.get("client_id", None)
  175. refresh_token = request_dict.get("refresh_token", None)
  176. logger = logging.getLogger('django')
  177. logger.info('token-------------begin--------')
  178. logger.info(code)
  179. logger.info(client_id)
  180. logger.info(refresh_token)
  181. logger.info(request_dict)
  182. print('client_id:')
  183. print(client_id)
  184. user_qs = UserModel.objects.filter(code=code)
  185. if not user_qs.exists():
  186. user_qs = UserModel.objects.filter(refresh_token=refresh_token)
  187. if user_qs.exists():
  188. access_token = CommonService.encrypt_data(randomlength=32)
  189. refresh_token = CommonService.encrypt_data(randomlength=32)
  190. is_update = user_qs.update(access_token=access_token, refresh_token=refresh_token)
  191. print(is_update)
  192. if is_update:
  193. res_json = {
  194. "access_token": access_token,
  195. "token_type": "bearer",
  196. "expires_in": 3600,
  197. "refresh_token": refresh_token,
  198. # 'test': 'joker'
  199. }
  200. logger.info(res_json)
  201. return JsonResponse(res_json)
  202. else:
  203. logger.info({'msg': 'error'})
  204. return JsonResponse({'msg': 'error'})
  205. else:
  206. res_json = {'msg': 'code not exists'}
  207. return JsonResponse(res_json)
  208. def runSendRtspMsg_thread(UID, PWD, MSG):
  209. command = "./pushtool {UID} {PWD} {MSG} 1".format(UID=UID, PWD=PWD, MSG=MSG)
  210. print('command=>{command}'.format(command=command))
  211. try:
  212. back = subprocess. \
  213. Popen(command, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE). \
  214. communicate(timeout=10)
  215. except Exception as e:
  216. return False
  217. else:
  218. print("back0----", back[0].decode()) # 注意需要进行解码操作,默认输出的是字节
  219. print("back1----", back[1].decode()) # back是一个元祖,可以通过元祖取值的方式获取结果
  220. return True
  221. class oa2RtspStartView(TemplateView):
  222. def post(self, request, *args, **kwargs):
  223. request.encoding = 'utf-8'
  224. request_dict = request.POST
  225. return self.validate(request_dict)
  226. def get(self, request, *args, **kwargs):
  227. request.encoding = 'utf-8'
  228. request_dict = request.GET
  229. return self.validate(request_dict)
  230. def validate(self, request_dict):
  231. st = request_dict.get("st", 0)
  232. uid = request_dict.get("id", '')
  233. access_token = request_dict.get("access_token", '')
  234. skill_name = request_dict.get("skill_name", 'zosi smart')
  235. user_qs = UserModel.objects.filter(access_token=access_token)
  236. if not user_qs.exists():
  237. return JsonResponse({'错误': '用户数据不存在'})
  238. ur_qs = UidRtspModel.objects.filter(uid=uid).values('user_id', 'uid', 'nick', 'rtsp_url', 'password')
  239. if not ur_qs.exists():
  240. return JsonResponse({'错误': 'uid数据不存在'})
  241. # 确认设备的用户地区
  242. region = 'US'
  243. user_id = ur_qs[0]['user_id']
  244. user_qs = UserModel.objects.filter(userID=user_id).values('region_code')
  245. if user_qs.exists():
  246. region = user_qs[0]['region_code']
  247. UID = ur_qs[0]['uid']
  248. nick = ur_qs[0]['nick']
  249. PWD = ur_qs[0]['password']
  250. stream_name = ur_qs[0]['rtsp_url']
  251. channel = '0'
  252. if '_' in UID:
  253. # 多通道设备
  254. channel = UID[-1:]
  255. UID = UID[:-2]
  256. RESP_SERVER_DOMAIN = RESP_SERVER_DOMAIN_DATA[region]
  257. MSG = '{}://{}:8554/{}'.format(RTSP_PREFIX, RESP_SERVER_DOMAIN, stream_name)
  258. logger = logging.getLogger('django')
  259. logger.info('------{} 开始向设备下发推流指令------'.format(skill_name))
  260. # 此处后续应该用异步去发送指令
  261. if int(st) == 1:
  262. send_flag = self.runSendStop(UID, PWD, MSG)
  263. logger.info('----------send_flag---st=1-----------------')
  264. if send_flag:
  265. return JsonResponse({'msg': 'stop yes', 'code': 0})
  266. else:
  267. return JsonResponse({'msg': 'stop no', 'code': 0})
  268. # pushtool指令
  269. command = "./pushtool {UID} {PWD} {MSG} 1 {channel}".format(UID=UID, PWD=PWD, MSG=MSG, channel=channel)
  270. # 请求MQTT发布消息
  271. url = '{}/iot/requestPublishMessage'.format(SERVER_PREFIX)
  272. requests_data = {'UID': UID, 'rtsp': MSG, 'enable': '1'} # 1: 开始推流,0: 停止推流; channel: 推流通道
  273. r = requests.post(url, requests_data)
  274. if r.status_code == 200:
  275. res = r.json()
  276. logger.info('请求MQTT发布消息参数:{},result_code: {}'.format(requests_data, res['result_code']))
  277. if res['result_code'] == 0:
  278. logger.info('请求MQTT下发指令成功---正式服')
  279. elif res['result_code'] == 10044:
  280. url = '{}/iot/requestPublishMessage'.format(SERVER_PREFIX_TEST) # 测试服务器
  281. r = requests.post(url, requests_data)
  282. if r.status_code == 200:
  283. res = r.json()
  284. if res['result_code'] == 0:
  285. logger.info('请求MQTT下发指令成功---测试服')
  286. else:
  287. self.runSendRtspMsg(logger, region, command)
  288. else:
  289. self.runSendRtspMsg(logger, region, command)
  290. else:
  291. self.runSendRtspMsg(logger, region, command)
  292. else: # 使用pushtool通知设备推流
  293. self.runSendRtspMsg(logger, region, command)
  294. # 拉流地址
  295. rtsp_uri = '{}://{}:443/{}'.format(RTSP_PREFIX, RESP_SERVER_DOMAIN, stream_name)
  296. stop_time = int(time.time()) + 2 * 60
  297. expirationTime = time.strftime('%Y-%m-%dT%H:%MZ', time.localtime(stop_time))
  298. res_json = {
  299. 'uid': UID,
  300. 'pwd': PWD,
  301. 'msg': MSG,
  302. 'uri': rtsp_uri,
  303. 'endpointId': uid,
  304. 'friendlyName': nick,
  305. 'manufacturerName': skill_name,
  306. 'expirationTime': expirationTime,
  307. 'description': 'Camera connected via {}'.format(skill_name),
  308. 'audioCodecs': 'ACC',
  309. 'videoCodecs': 'H264',
  310. 'protocols': ['RTSP'],
  311. 'idleTimeoutSeconds': 5,
  312. 'modelName': 'P1425-LE',
  313. 'authorizationTypes': ['NONE'],
  314. 'manufacturerId': 'zosi-ACCC8E5E7513',
  315. 'resolutions': {'width': 640, 'height': 360},
  316. }
  317. logger.info('------------返回控制摄像头的信息---------------: {}'.format(res_json))
  318. return JsonResponse(res_json, safe=False)
  319. def runReqRtspMsg(self, UID, PWD, MSG):
  320. request_url = 'http://localhost:5000/?UID={UID}&MSG={MSG}&CMD=1&PWD={PWD}'. \
  321. format(UID=UID, PWD=PWD, MSG=MSG)
  322. res = requests.get(url=request_url)
  323. print(res)
  324. return True
  325. # 触发此方法,让摄像头推流到MSG流地址
  326. def runSendRtspMsg(self, logger, region, command):
  327. logger.info('------------推流指令: {}---------------'.format(command))
  328. if region == 'CN':
  329. logger.info('------------国内发送推流指令---------------')
  330. url = "http://52.83.252.41:7880/alexa/command?command={command}".format(command=command)
  331. # 请求国内服务器调用pushtool
  332. try:
  333. requests.get(url=url, timeout=10)
  334. except Exception as e:
  335. logger.info('请求国内服务器调用pushtool异常: {}'.format(repr(e)))
  336. else:
  337. logger.info('------------国外发送推流指令---------------')
  338. try:
  339. back = subprocess.Popen(command, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE). \
  340. communicate(timeout=10)
  341. logger.info('back: {}'.format(str(back[0].decode()) + str(back[1].decode())))
  342. except Exception as e:
  343. self.runSendRtspMsg(logger, 'CN', command) # 调用失败时尝试用国内的发送
  344. logger.info('调用pushtool异常: {}'.format(repr(e)))
  345. def runSendStop(self, UID, PWD, MSG):
  346. command = "./pushtool {UID} {PWD} {MSG} 0".format(UID=UID, PWD=PWD, MSG=MSG)
  347. print('command=>{command}'.format(command=command))
  348. try:
  349. back = subprocess.Popen(command, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE). \
  350. communicate(timeout=10)
  351. except Exception as e:
  352. return False
  353. else:
  354. print("back0----", back[0].decode()) # 注意需要进行解码操作,默认输出的是字节
  355. print("back1----", back[1].decode()) # back是一个元祖,可以通过元祖取值的方式获取结果
  356. return True
  357. class oa2DiscoveryDevice(TemplateView):
  358. def post(self, request, *args, **kwargs):
  359. request.encoding = 'utf-8'
  360. request_dict = request.POST
  361. return self.validate(request_dict)
  362. def get(self, request, *args, **kwargs):
  363. request.encoding = 'utf-8'
  364. request_dict = request.GET
  365. return self.validate(request_dict)
  366. def validate(self, request_dict):
  367. # 增加对code和client_id的校验代码,返回access_token和refresh_token
  368. skill_name = request_dict.get("skill_name", 'zosi smart')
  369. access_token = request_dict.get("access_token", None)
  370. logger = logging.getLogger('django')
  371. logger.info('--------{} 开始搜索设备--------'.format(skill_name))
  372. response = ResObject()
  373. user_qs = UserModel.objects.filter(access_token=access_token)
  374. if not user_qs.exists():
  375. return response.json(500, res={'msg': '用户数据不存在'})
  376. user = user_qs[0]
  377. userID = user.userID
  378. logger.info('userID: {}'.format(userID))
  379. # 更新事件网关接口
  380. alexAuth = AlexaAuthModel.objects.filter(token=access_token, skill_name=skill_name).order_by('-addTime')
  381. if alexAuth.exists():
  382. auth_res = alexAuth.values()
  383. event_access_token = auth_res[0]['access_token']
  384. event_refresh_token = auth_res[0]['refresh_token']
  385. event_token = auth_res[0]['token']
  386. event_expiresTime = auth_res[0]['expiresTime']
  387. event_addTime = auth_res[0]['addTime']
  388. event_updTime = auth_res[0]['updTime']
  389. event_alexa_region = auth_res[0]['alexa_region']
  390. AlexaAuthModel.objects.filter(userID=userID).delete()
  391. alexAuth.delete()
  392. logger.info('update_event_access_token')
  393. logger.info(event_token)
  394. AlexaAuthModel.objects.create(
  395. userID=userID,
  396. access_token=event_access_token,
  397. refresh_token=event_refresh_token,
  398. token=event_token,
  399. expiresTime=event_expiresTime,
  400. addTime=event_addTime,
  401. updTime=event_updTime,
  402. alexa_region=event_alexa_region,
  403. skill_name=skill_name,
  404. )
  405. auth_request_url = '{}/oalexa/discoveryuid'.format(SERVER_PREFIX)
  406. requests_data = {'sid': 'admin', 'sst': 'admin', 'alexa_user_id': userID}
  407. res = requests.post(url=auth_request_url, data=requests_data)
  408. res_json = res.json()
  409. logger.info('正式服务器响应: {}'.format(res_json))
  410. test_flag = False # 用来区分测试服务器,后面删掉
  411. # 添加测试服务器测试
  412. if res_json['result_code'] != 0:
  413. auth_request_url = '{}/oalexa/discoveryuid'.format(SERVER_PREFIX_TEST)
  414. res = requests.post(url=auth_request_url, data=requests_data)
  415. res_json = res.json()
  416. test_flag = True
  417. logger.info('请求服务器url: {}'.format(auth_request_url))
  418. logger.info('服务器响应: {}'.format(res_json))
  419. if res_json['result_code'] != 0:
  420. return response.json(500, res={'msg': '请求业务服务器接口result_code不为0'})
  421. uid_arr = res_json['result']['uid_arr']
  422. rtko = tkObject(rank=1)
  423. now_time = int(time.time())
  424. user.uid_rtsp.clear()
  425. res_json = []
  426. uid_rtsp_id_list = []
  427. for uid_a in uid_arr:
  428. uid = uid_a['uid']
  429. nick = uid_a['nick']
  430. rtsp_url = rtko.encrypt(data=uid)
  431. region = 'EU' if uid_a['region'] == 'EU' else 'US'
  432. if test_flag:
  433. multi_channel = uid_a['multi_channel']
  434. if multi_channel:
  435. # 多通道设备: uid_通道号
  436. uid += '_' + str(uid_a['channel'])
  437. try:
  438. uid_rtsp_qs = UidRtspModel.objects.get(uid=uid)
  439. except UidRtspModel.DoesNotExist:
  440. uid_rtsp_qs = UidRtspModel.objects.create(user_id=userID, uid=uid, nick=nick, region=region,
  441. password=uid_a['password'],
  442. rtsp_url=rtsp_url, addTime=now_time, updTime=now_time)
  443. else:
  444. uid_rtsp_qs.nick = nick
  445. uid_rtsp_qs.region = region
  446. uid_rtsp_qs.password = uid_a['password']
  447. uid_rtsp_qs.save()
  448. uid_rtsp_id_list.append(uid_rtsp_qs.id)
  449. RESP_SERVER_DOMAIN = RESP_SERVER_DOMAIN_DATA[region]
  450. rtsp_uri = '{}://{}:443/{}'.format(RTSP_PREFIX, RESP_SERVER_DOMAIN, rtsp_url)
  451. ur_data = {
  452. 'uri': rtsp_uri,
  453. 'endpointId': uid,
  454. 'friendlyName': nick,
  455. 'manufacturerName': skill_name,
  456. 'description': 'Camera connected via {}'.format(skill_name),
  457. 'protocols': ['RTSP'],
  458. 'audioCodecs': ['ACC'],
  459. 'videoCodecs': ['H264'],
  460. 'modelName': 'P1425-LE',
  461. 'authorizationTypes': ['NONE'],
  462. 'manufacturerId': 'zosi-ACCC8E5E7513',
  463. 'resolutions': [{'width': 640, 'height': 360}],
  464. }
  465. res_json.append(ur_data)
  466. user.uid_rtsp.add(*uid_rtsp_id_list)
  467. logger.info('搜索设备返回值: {}'.format(res_json))
  468. return JsonResponse(res_json, safe=False)
  469. class oa2DiscoverySwitch(TemplateView):
  470. def post(self, request, *args, **kwargs):
  471. request.encoding = 'utf-8'
  472. request_dict = request.POST
  473. return self.validate(request_dict)
  474. def get(self, request, *args, **kwargs):
  475. request.encoding = 'utf-8'
  476. request_dict = request.GET
  477. return self.validate(request_dict)
  478. def validate(self, request_dict):
  479. # 增加对code和client_id的校验代码,返回access_token和refresh_token
  480. skill_name = request_dict.get("skill_name", 'loocam')
  481. access_token = request_dict.get("access_token", None)
  482. logger = logging.getLogger('django')
  483. logger.info('--------{} 开始搜索设备--------'.format(skill_name))
  484. user_qs = UserModel.objects.filter(access_token=access_token)
  485. if not user_qs.exists():
  486. return JsonResponse({'错误': '用户数据不存在'})
  487. response = ResObject()
  488. user = user_qs.first()
  489. userID = user.userID
  490. logger.info('userID: {}'.format(userID))
  491. # 更新事件网关接口
  492. alexAuth = AlexaAuthModel.objects.filter(token=access_token, skill_name=skill_name).order_by('-addTime')
  493. if alexAuth.exists():
  494. auth_res = alexAuth.values()
  495. event_access_token = auth_res[0]['access_token']
  496. event_refresh_token = auth_res[0]['refresh_token']
  497. event_token = auth_res[0]['token']
  498. event_expiresTime = auth_res[0]['expiresTime']
  499. event_addTime = auth_res[0]['addTime']
  500. event_updTime = auth_res[0]['updTime']
  501. event_alexa_region = auth_res[0]['alexa_region']
  502. AlexaAuthModel.objects.filter(userID=userID).delete()
  503. alexAuth.delete()
  504. logger.info('update_event_access_token')
  505. logger.info(event_token)
  506. AlexaAuthModel.objects.create(
  507. userID=userID,
  508. access_token=event_access_token,
  509. refresh_token=event_refresh_token,
  510. token=event_token,
  511. expiresTime=event_expiresTime,
  512. addTime=event_addTime,
  513. updTime=event_updTime,
  514. alexa_region=event_alexa_region,
  515. skill_name=skill_name,
  516. )
  517. auth_request_url = '{}/oalexa/discoveryswitch'.format(SERVER_PREFIX)
  518. requests_data = {'sid': 'admin', 'sst': 'admin', 'alexa_user_id': userID}
  519. res = requests.post(url=auth_request_url, data=requests_data)
  520. res_json = res.json()
  521. logger.info('正式服务器响应: {}'.format(res_json))
  522. # 添加测试服务器测试
  523. if res_json['result_code'] != 0:
  524. auth_request_url = '{}/oalexa/discoveryswitch'.format(SERVER_PREFIX_TEST)
  525. res = requests.post(url=auth_request_url, data=requests_data)
  526. res_json = res.json()
  527. logger.info('请求服务器url: {}'.format(auth_request_url))
  528. logger.info('服务器响应: {}'.format(res_json))
  529. if res_json['result_code'] != 0:
  530. return response.json(0, res={'msg': 'error'})
  531. switch_list = res_json['result']['switch_list']
  532. now_time = int(time.time())
  533. res_json = []
  534. for switch in switch_list:
  535. serial_number = switch['uid']
  536. nick = switch['nick']
  537. region = 'EU' if switch['region'] == 'EU' else 'EN'
  538. switch_info_qs = SwitchModel.objects.filter(serial_number=serial_number, userID=userID)
  539. if switch_info_qs.exists():
  540. switch_info_qs.update(nick=nick, region=region, updTime=now_time)
  541. else:
  542. SwitchModel.objects.create(serial_number=serial_number, nick=nick, region=region, addTime=now_time,
  543. updTime=now_time, userID=userID)
  544. ur_data = {
  545. 'endpointId': serial_number,
  546. 'friendlyName': nick,
  547. 'manufacturerName': skill_name,
  548. 'description': 'Plug connected via {}'.format(skill_name),
  549. 'modelName': 'P1425-LE',
  550. 'manufacturerId': 'zosi-ACCC8E5E7513',
  551. }
  552. res_json.append(ur_data)
  553. logger.info('搜索设备返回值: {}'.format(res_json))
  554. return JsonResponse(res_json, safe=False)
  555. class powerController(TemplateView):
  556. def post(self, request, *args, **kwargs):
  557. request.encoding = 'utf-8'
  558. request_dict = request.POST
  559. return self.power_controller(request_dict)
  560. def get(self, request, *args, **kwargs):
  561. request.encoding = 'utf-8'
  562. request_dict = request.GET
  563. return self.power_controller(request_dict)
  564. def power_controller(self, request_dict):
  565. serial_number = request_dict.get('serial_number', '')
  566. access_token = request_dict.get('access_token', '')
  567. skill_name = request_dict.get('skill_name', 'loocam')
  568. power_controller = request_dict.get('power_controller', '')
  569. if not all([serial_number, access_token, skill_name]):
  570. return JsonResponse({'result_code': '500', '错误': '缺少参数'})
  571. user_qs = UserModel.objects.filter(access_token=access_token)
  572. if not user_qs.exists():
  573. return JsonResponse({'result_code': '500', '错误': '用户数据不存在'})
  574. userID = user_qs.first().userID
  575. switch_qs = SwitchModel.objects.filter(serial_number=serial_number, userID=userID).values('nick', 'region')
  576. if not switch_qs.exists():
  577. return JsonResponse({'result_code': '500', '错误': 'serial_number数据不存在'})
  578. logger = logging.getLogger('django')
  579. logger.info('{} 控制插座 {}'.format(skill_name, serial_number))
  580. # 请求MQTT发布消息
  581. url = '{}/api/loocam/open/socket/alexa-socket-switch'.format(SERVER_PREFIX) # 国外服务器
  582. requests_data = {'serial_number': serial_number, 'power_controller': power_controller} # TurnOn, TurnOff
  583. r = requests.post(url, requests_data)
  584. if r.status_code != 200:
  585. return JsonResponse({'result_code': '500', '错误': '请求国外服务器响应异常'})
  586. res = r.json()
  587. logger.info('国外服务器返回状态: {}'.format(res))
  588. if res['result_code'] != 0:
  589. url = '{}/api/loocam/open/socket/alexa-socket-switch'.format(SERVER_PREFIX_TEST) # 测试服务器
  590. requests_data = {'serial_number': serial_number, 'power_controller': power_controller} # TurnOn, TurnOff
  591. r = requests.post(url, requests_data)
  592. if r.status_code != 200:
  593. return JsonResponse({'result_code': '500', '错误': '请求测试服务器响应异常'})
  594. res = r.json()
  595. logger.info('测试服务器返回状态: {}'.format(res))
  596. if res['result_code'] != 0:
  597. return JsonResponse({'result_code': '500', '错误': '请求MQTT下发指令失败'})
  598. else:
  599. logger.info('请求MQTT下发指令成功')
  600. return JsonResponse({'result_code': '0'})
  601. else:
  602. logger.info('请求MQTT下发指令成功')
  603. return JsonResponse({'result_code': '0'})
  604. class VesseTest(TemplateView):
  605. def get(self, request, *args, **kwargs):
  606. request.encoding = 'utf-8'
  607. operation = kwargs.get('operation')
  608. return self.validation(request.GET, operation, request)
  609. def post(self, request, *args, **kwargs):
  610. request.encoding = 'utf-8'
  611. operation = kwargs.get('operation')
  612. return self.validation(request.POST, operation, request)
  613. def validation(self, request_dict, operation, request):
  614. response = ResponseObject()
  615. if operation == 'get-token': # 获取token
  616. return self.get_token(response)
  617. elif operation == 'get-user-id': # 获取userid
  618. return self.get_user_id(request_dict, response, request)
  619. elif operation == 'get-user-info': # 获取用户信息
  620. return self.get_user_info(request_dict, response, request)
  621. def get_token(self, response):
  622. data = {
  623. 'corpid': 'ww467ec1685e8262e6',
  624. 'corpsecret': 'IeUoaQ-0hEhEduCQq1zyfVXjfeZpMsThK1nklszRzUY'
  625. }
  626. try:
  627. token_url = 'https://qyapi.weixin.qq.com/cgi-bin/gettoken'
  628. token_response = requests.get(token_url, params=data)
  629. if token_response.status_code == 200:
  630. data = token_response.json()
  631. access_token = data.get("access_token")
  632. if access_token:
  633. return response.json(0, {'access_token': access_token})
  634. else:
  635. return response.json(0, "Failed to get AccessToken.")
  636. else:
  637. code = token_response.status_code
  638. content = token_response.content
  639. return response.json(code, content)
  640. except requests.exceptions.RequestException as e:
  641. print(e)
  642. return response.json(500, repr(e))
  643. def get_user_id(self, request_dict, response, request):
  644. access_token = request_dict.get('access_token', None)
  645. code = request_dict.get('code', None)
  646. if not all([access_token, code]):
  647. return response.json(444, 'error: access_token, code')
  648. data = {
  649. 'access_token': access_token,
  650. 'code': code
  651. }
  652. try:
  653. token_url = 'https://qyapi.weixin.qq.com/cgi-bin/auth/getuserinfo'
  654. token_response = requests.get(token_url, params=data)
  655. if token_response.status_code == 200:
  656. data = token_response.json()
  657. userid = data.get("userid")
  658. if userid:
  659. return response.json(0, {'userid': userid})
  660. else:
  661. code = token_response.status_code
  662. content = token_response.content
  663. return response.json(code, content)
  664. except Exception as e:
  665. print(e)
  666. return response.json(500, repr(e))
  667. def get_user_info(self, request_dict, response, request):
  668. access_token = request_dict.get('access_token', None)
  669. userid = request_dict.get('userid', None)
  670. if not all([access_token, userid]):
  671. return response.json(444, 'error: access_token, userid')
  672. data = {
  673. 'access_token': access_token,
  674. 'userid': userid
  675. }
  676. try:
  677. token_url = 'https://qyapi.weixin.qq.com/cgi-bin/user/get'
  678. token_response = requests.get(token_url, params=data)
  679. if token_response.status_code == 200:
  680. data = token_response.json()
  681. userid = data.get("userid")
  682. name = data.get('name')
  683. position = data.get('position')
  684. status = data.get('status')
  685. if userid:
  686. url_data = {
  687. 'userid': userid,
  688. 'name': name,
  689. 'position': position,
  690. 'status': status
  691. }
  692. return response.json(0, {'data': url_data})
  693. else:
  694. code = token_response.status_code
  695. content = token_response.content
  696. return response.json(code, content)
  697. except Exception as e:
  698. print(e)
  699. return response.json(500, repr(e))