فهرست منبع

兼容分区欧洲用户登录(暂时注释起来)

locky 2 سال پیش
والد
کامیت
9deda05039
4فایلهای تغییر یافته به همراه54 افزوده شده و 283 حذف شده
  1. 4 18
      azoauth/config.py
  2. 20 245
      controller/deviceStatus.py
  3. 26 17
      controller/index.py
  4. 4 3
      model/models.py

+ 4 - 18
azoauth/config.py

@@ -1,30 +1,16 @@
-#!/usr/bin/env python3  
-# -*- coding: utf-8 -*-  
-"""
-@Copyright (C) ansjer cop Video Technology Co.,Ltd.All rights reserved.
-@AUTHOR: ASJRD018
-@NAME: azoauth
-@software: PyCharm
-@DATE: 2020/3/6 10:14
-@Version: python3.6
-@MODIFY DECORD:ansjer dev
-@file: config.py
-@Contact: chanjunkai@163.com
-"""
 
 RESP_SERVER_DOMAIN_DATA = {
     'CN': 'rtsp.zositech.xyz',
     'EN': 'rtsp.zositech.com',
     'EU': 'rtspeu.zositech.com'
 }
+
 SERVER_PREFIX = 'http://www.dvema.com'
+SERVER_PREFIX_EU = 'http://api.zositeche.com'
 SERVER_PREFIX_TEST = 'http://test.zositechc.cn'
-#Easydarwin
-# PORT_PREFIX = '8554'
-#PORT_PREFIX = '554'
-# PORT_PREFIX = '443'
-#RTSP_PREFIX = 'rtsps'
+
 RTSP_PREFIX = 'rtsp'
+
 ALEXA_EVENT_API = {
     # 美洲
     'US': 'https://api.amazonalexa.com/v3/events',

+ 20 - 245
controller/deviceStatus.py

@@ -24,8 +24,6 @@ from django.utils.decorators import method_decorator
 from django.views.decorators.csrf import csrf_exempt
 from azoauth.config import *
 
-rtspServer = "rtsp.zositech.com,3.16.66.144"
-
 
 class deviceStatus(TemplateView):
     @method_decorator(csrf_exempt)
@@ -44,25 +42,17 @@ class deviceStatus(TemplateView):
 
     def validation(self, request_dict, request, operation):
         response = ResponseObject()
-        if operation is None:
-            return JsonResponse({'code': 404, 'msg': 'not found'})
         if operation == 'saveAccessToken':
             return self.saveAccessToken(request_dict)
-        if operation == 'getAccessToken':
-            return self.getAccessToken(request_dict, response)
-        if operation == 'addOrUpdate':
-            return self.addOrUpdate(request_dict, response)
-        if operation == 'addOrUpdateV2':
+        elif operation == 'addOrUpdateV2':
             return self.addOrUpdateV2(request_dict)
-        if operation == 'addOrUpdateSwitch':
+        elif operation == 'addOrUpdateSwitch':
             return self.addOrUpdateSwitch(request_dict)
-        if operation == 'delete':
+        elif operation == 'delete':
             return self.delete(request_dict)
-        if operation == 'stopPush':
-            return self.notifiesDeviceStopPush(request_dict, response)
-        if operation == 'stateReport':
+        elif operation == 'stateReport':
             return self.StateReport(request_dict)
-        if operation == 'deleteSwitch':
+        elif operation == 'deleteSwitch':
             return self.deleteSwitch(request_dict)
 
     def saveAccessToken(self, request_dict):
@@ -100,127 +90,9 @@ class deviceStatus(TemplateView):
                 )
             return JsonResponse({'code': 200, 'msg': 'success'})
         except Exception as e:
-            logger.info('授权登录接口异常: error_ine:{}, error_msg:{}'.format(e.__traceback__.tb_lineno, repr(e)))
+            logger.info('授权登录接口异常: error_line:{}, error_msg:{}'.format(e.__traceback__.tb_lineno, repr(e)))
             return JsonResponse({'code': 500, 'msg': 'error'})
 
-    def getAccessToken(self, request_dict, response):
-        logger = logging.getLogger('django')
-        logger.info('-------------getAccessToken')
-        # logger.info(request_dict)
-        return JsonResponse({'code': 200, 'msg': 'success'})
-
-    # 向alex事件网关发送更新设备操作,已改成V2接口,后期可删掉
-    def addOrUpdate(self, request_dict, response):
-        logger = logging.getLogger('django')
-        logger.info('in__________________________first')
-
-        UID = request_dict.get("UID", '')
-        userID = request_dict.get("userID", '')
-        uid_nick = request_dict.get("uid_nick", '')
-        encrypt_pwd = request_dict.get("password", '')
-        region = request_dict.get("region", 'EN')
-        if UID == '' or userID == '' or uid_nick == '' or encrypt_pwd == '':
-            return JsonResponse({'code': 101, 'msg': 'fail'})
-
-        commonService = CommonService()
-        password = commonService.decode_pwd(encrypt_pwd)
-        alexAuth = AlexaAuthModel.objects.filter(userID=userID)
-        if not alexAuth.exists():
-            logger.info('not found user')
-            logger.info(UID)
-            return JsonResponse({'code': 102, 'msg': 'not found user'})
-        info = alexAuth.values()
-        expiresTime = info[0]['expiresTime']
-        now_time = int(time.time())
-        access_token = info[0]['access_token']
-        refresh_token = info[0]['refresh_token']
-        alexa_region = info[0]['alexa_region']
-
-        if now_time > expiresTime:
-            logger.info(refresh_token)
-            res = self.getRefreshToken(refresh_token)
-            logger.info(res)
-            if ('error' not in res):
-                alexAuth.update(
-                    access_token=res['access_token'],
-                    refresh_token=res['refresh_token'],
-                    expiresTime=now_time + 3000,
-                    updTime=now_time,
-                )
-                access_token = res['access_token']
-            else:
-                logger.info('get refresh_token fail')
-                return JsonResponse({'code': 102, 'msg': 'get refresh_token fail'})
-
-        # 添加rtsp记录
-        rtko = tkObject(rank=1)
-        rtsp_url = rtko.encrypt(data=UID)
-        try:
-            uid_rtsp_qs = UidRtspModel.objects.get(uid=UID)
-        except UidRtspModel.DoesNotExist:
-            uid_rtsp_qs = UidRtspModel.objects.create(uid=UID, password=password,
-                                                      nick=uid_nick, addTime=now_time,
-                                                      updTime=now_time, rtsp_url=rtsp_url,
-                                                      region=region)
-        else:
-            # if uid_rtsp_qs.password != uid_a['password']:
-            uid_rtsp_qs.password = password
-            uid_rtsp_qs.nick = uid_nick
-            uid_rtsp_qs.region = 'EN'
-            uid_rtsp_qs.save()
-
-        api_uri = ALEXA_EVENT_API[alexa_region]
-        messageId = str(uuid.uuid4()).strip()
-        bearer_access_token = "Bearer {access_token}".format(access_token=access_token)
-        headers = {"content-type": "application/json", "Authorization": bearer_access_token}
-        payload_json = {
-            "event": {
-                "header": {
-                    "namespace": "Alexa.Discovery",
-                    "name": "AddOrUpdateReport",
-                    "payloadVersion": "3",
-                    "messageId": messageId,
-                },
-                "payload": {
-                    "endpoints": [
-                        {
-                            "endpointId": UID,
-                            "manufacturerName": "zosi smart",
-                            "modelName": "P1425-LE",
-                            "friendlyName": uid_nick,
-                            "description": "Camera connected via zosi smart",
-                            "displayCategories": ["CAMERA"],
-                            "capabilities": [
-                                {
-                                    "type": "AlexaInterface",
-                                    "interface": "Alexa.CameraStreamController",
-                                    "version": "3",
-                                    "cameraStreamConfigurations": [
-                                        {
-                                            "protocols": ["RTSP"],
-                                            "resolutions": [{"width": 1280, "height": 720}],
-                                            "authorizationTypes": ["NONE"],
-                                            "videoCodecs": ["H264"],
-                                            "audioCodecs": ["ACC"],
-                                        }
-                                    ],
-                                }
-                            ],
-                        }
-                    ],
-                    "scope": {
-                        "type": "BearerToken",
-                        "token": 'sdf',
-                    },
-                },
-            }
-        }
-
-        response = requests.post(api_uri, json=payload_json, headers=headers)
-        logger.info('--------addOrUpdate_response')
-        logger.info(response)
-        return JsonResponse({'res': 'success'})
-
     # 向alexa事件网关发送更新设备操作V2接口
     def addOrUpdateV2(self, request_dict):
         logger = logging.getLogger('django')
@@ -282,16 +154,15 @@ class deviceStatus(TemplateView):
                 # 创建UidRtsp数据
                 if channel == 1:
                     # 单通道设备
-                    UidRtspModel.objects.create(uid=UID, nick=data_list[0]['uid_nick'], region=region,
-                                                rtsp_url=rtsp_url,
-                                                password=password, addTime=now_time, updTime=now_time)
+                    UidRtspModel.objects.create(user_id=userID, uid=UID, nick=data_list[0]['uid_nick'], region=region,
+                                                rtsp_url=rtsp_url, password=password, addTime=now_time, updTime=now_time)
                 else:
                     # 多通道设备
                     bulk = []
                     for data in data_list:
                         uid = UID + '_' + str(data['channel'])  # 多通道设备: uid_通道号
-                        uidRtsp = UidRtspModel(uid=uid, nick=data['uid_nick'], region=region, rtsp_url=rtsp_url,
-                                               password=password, addTime=now_time, updTime=now_time)
+                        uidRtsp = UidRtspModel(user_id=userID, uid=uid, nick=data['uid_nick'], region=region,
+                                               rtsp_url=rtsp_url, password=password, addTime=now_time, updTime=now_time)
                         bulk.append(uidRtsp)
                     UidRtspModel.objects.bulk_create(bulk)
             else:
@@ -335,7 +206,8 @@ class deviceStatus(TemplateView):
             logger.info('--------Alexa AddOrUpdateReport响应: {}--------'.format(response))
             return JsonResponse({'res': 'success'})
         except Exception as e:
-            logger.info('--------添加/更新设备信息V2异常--------: {}'.format(repr(e)))
+            logger.info('--------添加/更新设备信息V2异常--------:error_line:{}, error_msg:{}'.
+                        format(e.__traceback__.tb_lineno, repr(e)))
 
     # 向alexa事件网关发送更新设备操作接口
     def addOrUpdateSwitch(self, request_dict):
@@ -457,10 +329,10 @@ class deviceStatus(TemplateView):
             logger.info('--------Alexa AddOrUpdateReport响应: {}--------'.format(response))
             return JsonResponse({'res': 'success'})
         except Exception as e:
-            logger.info('--------添加/更新插座信息异常--------: {}'.format(repr(e)))
+            logger.info('--------添加/更新插座信息异常--------:error_line:{}, error_msg:{}'.
+                        format(e.__traceback__.tb_lineno, repr(e)))
             return JsonResponse({'res': 'error'})
 
-
     # 向alexa事件网关发送插座状态操作接口
     def StateReport(self, request_dict):
         logger = logging.getLogger('django')
@@ -501,7 +373,8 @@ class deviceStatus(TemplateView):
                 res = {'state': 'OFF'}
             return response.json(0, res=res)
         except Exception as e:
-            logger.info('--------上传插座状态异常--------: {}'.format(repr(e)))
+            logger.info('--------上传插座状态异常--------:error_line:{}, error_msg:{}'.
+                        format(e.__traceback__.tb_lineno, repr(e)))
             return response.json(10, res={'msg': '上报状态异常'})
 
     def append_endpoint(self, data_list, channel):
@@ -613,7 +486,8 @@ class deviceStatus(TemplateView):
             logger.info('--------Alexa DeleteReport响应: {}--------'.format(response))
             return JsonResponse({'res': 'success'})
         except Exception as e:
-            logger.info('--------删除设备异常--------: {}'.format(repr(e)))
+            logger.info('--------删除设备异常--------:error_line:{}, error_msg:{}'.
+                        format(e.__traceback__.tb_lineno, repr(e)))
 
     # 向alexa事件网关发送删除插座操作
     def deleteSwitch(self, request_dict):
@@ -691,7 +565,8 @@ class deviceStatus(TemplateView):
             logger.info('--------Alexa DeleteReport响应: {}--------'.format(response))
             return JsonResponse({'res': 'success'})
         except Exception as e:
-            logger.info('--------删除设备异常--------: {}'.format(repr(e)))
+            logger.info('--------删除设备异常--------:error_line:{}, error_msg:{}'.
+                        format(e.__traceback__.tb_lineno, repr(e)))
             return JsonResponse({'res': 'error'})
 
     def getRefreshToken(self, refresh_token, skill_name):
@@ -718,103 +593,3 @@ class deviceStatus(TemplateView):
         res = requests.post(auth_request_url, payload, headers)
         request_json = res.json()
         return request_json
-
-    def notifiesDeviceStopPush(self, request_dict, response):
-        play_url = "http://rtsp.zositech.com:10008/api/v1/players"
-        push_url = "http://rtsp.zositech.com:10008/api/v1/pushers"
-        try:
-            # queryPlay = requests.get(url=play_url, timeout=5)
-            # qplay = queryPlay.json()
-
-            queryPush = requests.get(url=push_url, timeout=5)
-            qpush = queryPush.json()
-        except Exception as e:
-            return response.json(103, res='query fail')
-        else:
-            # response.json(103, res=list(qplay))
-            # 正在拉流的ID
-            # play_rows = qplay['rows']
-            # play_paths = []
-            # for val in play_rows:
-            #     play_paths.append(val['path'])
-
-            # 正在推流的ID
-            push_rows = qpush['rows']
-            push_paths = []
-            for val in push_rows:
-                startAt = self.str_to_timestamp(val['startAt'])
-                run_time = int(time.time()) - int(startAt)
-                if run_time > 10 * 60:
-                    push_paths.append(val['path'])
-            send_flag = False
-            # 正在推流但是没有拉流的推流通知设备断掉
-            # for push_path in push_paths:
-            #     if push_path not in play_paths:
-            #         path_list = push_path.split('/')
-            #         has_rtsp_url = UidRtspModel.objects.filter(rtsp_url=path_list[-1]).values('uid','password')
-            #         # has_rtsp_url = UidRtspModel.objects.filter(rtsp_url='RFJrWk9OVVJPUVRnM1IxaFNXazFFUXpFeE1VRT1U').values('uid')
-            #         if has_rtsp_url.exists():
-            #             send_flag = self.runSendStop(has_rtsp_url[0]['uid'], has_rtsp_url[0]['password'], push_path)
-            # if send_flag:
-            #     return JsonResponse({'res':'success'})
-            # else:
-            #     return JsonResponse({'res':'fail'})
-
-            success = 0
-            for push_path in push_paths:
-                path_list = push_path.split('/')
-                has_rtsp_url = UidRtspModel.objects.filter(rtsp_url=path_list[-1]).values('uid', 'password')
-                # has_rtsp_url = UidRtspModel.objects.filter(rtsp_url='RFJrWk9OVVJPUVRnM1IxaFNXazFFUXpFeE1VRT1U').values('uid')
-                if has_rtsp_url.exists():
-                    send_flag = self.runSendStop(has_rtsp_url[0]['uid'], has_rtsp_url[0]['password'], push_path)
-                    if send_flag:
-                        success += 1
-            return JsonResponse({'successStopNum': success})
-
-    # 把格式化时间转换成时间戳
-    def str_to_timestamp(self, str_time=None, format='%Y-%m-%d %H:%M:%S'):
-        if str_time:
-            time_tuple = time.strptime(str_time, format)  # 把格式化好的时间转换成元祖
-            result = time.mktime(time_tuple)  # 把时间元祖转换成时间戳
-            return int(result)
-        return int(time.time())
-
-    # 本地时间转换为UTC  传入的本地时间戳 1531411200
-    # def local_to_utc(self, local_ts, utc_format='%Y-%m-%dT%H:%MZ'):
-    #     import pytz
-    #     local_tz = pytz.timezone('Asia/Chongqing')    #定义本地时区
-    #     local_format = "%Y-%m-%d %H:%M:%S"               #定义本地时间format
-    #
-    #     time_str = time.strftime(local_format, time.localtime(local_ts))    #首先将本地时间戳转化为时间元组,用strftime格式化成字符串
-    #     dt = datetime.datetime.strptime(time_str, local_format)             #将字符串用strptime 转为为datetime中 datetime格式
-    #     local_dt = local_tz.localize(dt, is_dst=None)                       #给时间添加时区,等价于 dt.replace(tzinfo=pytz.timezone('Asia/Chongqing'))
-    #     utc_dt = local_dt.astimezone(pytz.utc)                              #astimezone切换时区
-    #     return utc_dt.strftime(utc_format)                                  #返回世界时间格式
-
-    # 触发此方法,让摄像头推流到MSG流地址
-    def runSendStop(self, UID, PWD, MSG):
-
-        command = "./pushtool {UID} {PWD} {MSG} 0".format(UID=UID, PWD=PWD, MSG=MSG)
-        # print('command=>{command}'.format(command=command))
-        command_url = "http://47.115.134.251/index.php?command={command}".format(command=command)
-        try:
-            exec_res = requests.get(url=command_url, timeout=1)
-            res = exec_res.json()
-            if res['code'] == 200:
-                return True
-        except Exception as e:
-            return False
-
-
-# 请求alexa事件网关接口失败错误码
-'''
-400 Bad Request	INVALID_REQUEST_EXCEPTION	消息无效,可能是因为缺少字段、不正确的值或格式错误的 JSON。根据文档检查邮件以验证邮件是否包含所有必需的字段。
-401 Unauthorized	INVALID_ACCESS_TOKEN_EXCEPTION	访问令牌无效,因为它已过期或格式错误。刷新令牌并重试请求。如果用户禁用您的技能,这也会使访问令牌失效。这意味着用户已吊销授权,您可以停止为他们发送更改报告。
-403 Forbidden	SKILL_NEVER_ENABLED_EXCEPTION	请确保将事件发送到正确的区域终结点。例如,北美中的事件应发送到北美终结点。
-403 Forbidden	INSUFFICIENT_PERMISSION_EXCEPTION	令牌没有所需的权限。确保该技能具有发送 Alexa 事件的权限。请参阅异步消息身份验证的步骤。
-404 Not Found	SKILL_NOT_FOUND_EXCEPTION	找不到与此令牌关联的技能 ID。当技能处于不同阶段(如认证)时生成用户的访问令牌时,将发生此错误。尝试禁用并重新启用此用户的技能。
-413 Payload Too Large	REQUEST_ENTITY_TOO_LARGE_EXCEPTION	事件有效负载的大小太大。请求中允许的最大终结点数为 300。以较小的有效负载发送邮件。
-429 Too Many Requests	THROTTLING_EXCEPTION	请求数过高。重新发送消息最多三次,每次发送尝试之间至少有一秒的间隔。
-500 Internal Server Error	INTERNAL_SERVICE_EXCEPTION	Alexa 发生错误,无法处理该消息。重新发送消息最多三次,每次发送尝试之间至少有一秒的间隔。如果问题仍然存在,请联系亚马逊支持。
-503 Service Unavailable	SERVICE_UNAVAILABLE_EXCEPTION	亚历克萨不能接受这条信息。重新发送消息最多三次,每次尝试之间至少有一秒的间隔。如果问题仍然存在,请联系亚马逊支持。
-'''

+ 26 - 17
controller/index.py

@@ -137,24 +137,26 @@ class loginHandleView(TemplateView):
         if client_id != 'azalexaclient' or response_type != 'code' or scope != 'profile':
             return response.json(10, res={'msg': 'error'}, extra={'msg': 'message wrong'})
 
+        # 请求美洲服登录接口
+        region_code = 'US'
         auth_request_url = '{SERVER_PREFIX}/oalexa/auth'.format(SERVER_PREFIX=SERVER_PREFIX)
         requests_data = {'userName': user, 'userPwd': pwd}
         res = requests.post(url=auth_request_url, data=requests_data)
         if res.status_code != 200:
             return response.json(10, res={'错误': '请求响应异常'})
         res_json = res.json()
-        logger.info('国外服务器响应: {}'.format(res_json))
-
-        # 添加测试服务器测试
-        if res_json['result_code'] != 0:
-            auth_request_url = '{SERVER_PREFIX}/oalexa/auth'.format(SERVER_PREFIX=SERVER_PREFIX_TEST)
-            res = requests.post(url=auth_request_url, data=requests_data)
-            if res.status_code != 200:
-                return response.json(10, res={'错误': '请求响应异常'})
-            res_json = res.json()
-
-        logger.info('请求服务器url: {}'.format(auth_request_url))
-        logger.info('服务器响应: {}'.format(res_json))
+        logger.info('美洲服务器响应: {}'.format(res_json))
+
+        # 如果result_code不为0且region_code为EU,请求欧洲服登录接口
+        # if res_json['result_code'] != 0 and res_json['result']['region_code'] == 'EU':
+        #     auth_request_url = '{SERVER_PREFIX}/oalexa/auth'.format(SERVER_PREFIX=SERVER_PREFIX_EU)
+        #     res = requests.post(url=auth_request_url, data=requests_data)
+        #     if res.status_code != 200:
+        #         return response.json(10, res={'错误': '请求响应异常'})
+        #     res_json = res.json()
+        #     logger.info('欧洲服务器响应: {}'.format(res_json))
+        #     if res_json['result_code'] != 0:
+        #         region_code = 'EU'
 
         if res_json['result_code'] != 0:
             return response.json(10, res={'msg': 'error'}, extra={'msg': res_json['reason']})
@@ -164,9 +166,9 @@ class loginHandleView(TemplateView):
         userID = res_json['result']['userID']
         user_qs = UserModel.objects.filter(userID=userID)
         if user_qs.exists():
-            user_qs.update(code=code, updTime=nowTime)
+            user_qs.update(region_code=region_code, code=code, updTime=nowTime)
         else:
-            UserModel.objects.create(userID=userID, code=code, addTime=nowTime, updTime=nowTime)
+            UserModel.objects.create(userID=userID, region_code=region_code, code=code, addTime=nowTime, updTime=nowTime)
             year_month = str(time.strftime('%Y%m', time.localtime(nowTime)))  # 获取当前年月
             user_count_qs = UserCountModel.objects.filter(skill_name=skill_name, year_month=year_month).values('amount')
             if not user_count_qs.exists():
@@ -271,14 +273,20 @@ class oa2RtspStartView(TemplateView):
         if not user_qs.exists():
             return JsonResponse({'错误': '用户数据不存在'})
 
-        ur_qs = UidRtspModel.objects.filter(uid=uid).values('uid', 'nick', 'rtsp_url', 'password', 'region')
+        ur_qs = UidRtspModel.objects.filter(uid=uid).values('user_id', 'uid', 'nick', 'rtsp_url', 'password')
         if not ur_qs.exists():
             return JsonResponse({'错误': 'uid数据不存在'})
 
+        # 确认设备的用户地区
+        region = 'US'
+        user_id = ur_qs[0]['user_id']
+        user_qs = UserModel.objects.filter(userID=user_id).values('region_code')
+        if user_qs.exists():
+            region = user_qs[0]['region_code']
+
         UID = ur_qs[0]['uid']
         nick = ur_qs[0]['nick']
         PWD = ur_qs[0]['password']
-        region = ur_qs[0]['region']
         stream_name = ur_qs[0]['rtsp_url']
 
         channel = '0'
@@ -496,7 +504,8 @@ class oa2DiscoveryDevice(TemplateView):
             try:
                 uid_rtsp_qs = UidRtspModel.objects.get(uid=uid)
             except UidRtspModel.DoesNotExist:
-                uid_rtsp_qs = UidRtspModel.objects.create(uid=uid, nick=nick, region=region, password=uid_a['password'],
+                uid_rtsp_qs = UidRtspModel.objects.create(user_id=userID, uid=uid, nick=nick, region=region,
+                                                          password=uid_a['password'],
                                                           rtsp_url=rtsp_url, addTime=now_time, updTime=now_time)
             else:
                 uid_rtsp_qs.nick = nick

+ 4 - 3
model/models.py

@@ -5,8 +5,8 @@ from django.db import models
 
 
 class UserModel(models.Model):
-    userID = models.CharField(blank=True, max_length=32, primary_key=True,
-                              verbose_name=u'用户ID', unique=True)
+    userID = models.CharField(blank=True, max_length=32, primary_key=True, unique=True, verbose_name='用户ID')
+    region_code = models.CharField(default='US', max_length=8, verbose_name='用户地区')  # US, EU
     code = models.CharField(max_length=32, unique=True, default='', verbose_name='授权码')
     access_token = models.CharField(max_length=64, unique=False, default='', verbose_name='访问令牌')
     refresh_token = models.CharField(max_length=64, unique=False, default='', verbose_name='刷新令牌')
@@ -41,6 +41,7 @@ class UserCountModel(models.Model):
 
 class UidRtspModel(models.Model):
     id = models.AutoField(primary_key=True)
+    user_id = models.CharField(default='', max_length=32, verbose_name='关联用户表的userID')
     nick = models.CharField(max_length=32, verbose_name=u'设备昵称', default='')
     uid = models.CharField(max_length=20, verbose_name=u'设备UID', default='', unique=True)
     password = models.CharField(max_length=32, verbose_name=u'设备密码', default='')
@@ -51,7 +52,7 @@ class UidRtspModel(models.Model):
 
     class Meta:
         ordering = ('-addTime',)
-        verbose_name = '用户表'
+        verbose_name = 'uid信息表'
         db_table = 'uid_rtsp'
 
     def __str__(self):