zoukankan      html  css  js  c++  java
  • 智能玩具开发者日志

    第一天

    智能玩具开发者日志

    新学的快捷键: Ctrl+ ] 是往里面缩进([外缩) ctrl+shift+]是无序列表(前面点的表示[是数字表示)

    1 获取幼教内容:

    • 选取某优质音乐网站
    • 使用requests模块,进入网页,关闭清除缓存的(disable cache) 点all的那个,然后点击某个音乐,在network里的Name里找到以album(专辑)开头的,点击preview查看,点击response获取数据
    • 然后爬取需要的音乐和封面(存到本地不同的文件夹中)
    • 通过 requests.get('https:w4a' )获得music,然后把.content写入音乐文件(用uuid4表示)以及封面图片,然后把音乐名等信息存入MongoDB中

    2. content_list 接口 获取内容数据

    • 从数据库获得所有信息 find
    • 改了_id成str,否则不能jsonify,传给前端(jsonify)
    • 前端接口调用数据,进行显示

    以下内容都是接口函数,

    3. get_cover 获取图片

    4. get_music 获取音乐

    • 因为音乐和图片在文件夹中,先os.path.join拼接一下
    • 通过send_file发送到网上,前端去http上请求封面和歌曲

    5. reg 注册用户

    • 前端传过来的数据里有 用户注册的信息(用.form.to_dict()接收)
    • 然后在这个字典中添加之后用户会使用的其他信息('bind_toys','friend_list',以及'avatar'头像(存储在前端))
    • 加到数据库Users表里 insert_one
    • 返回数据 通知一声说明注册成功 code:0

    6. login 用户登录

    7. auto_login 用户自动登录

    1. 从数据库Users表里查询登录信息find_one(to_dict())
      如果数据库和登录信息匹配 则返回前端  code:0 (jsonify) 
      同时返回查到的数据
      

    第二天

    1. scan_qr 用于DeviceKey的数据校验

    1. 先生成二维码,并存储到数据库里

      二维码字符通过uuid4 时间戳 加密 拼接而成	长度短且唯一	
      
      利用联图LT生成二维码,写入文件,并且把生成的二维码列表[{'device_key':qr},.写入数据库Devices
      
    2. 当扫描二维码时,走scan_qr接口

      判断二维码的device是否在 Devices可找到 find_one
      如果是: 返回二维码,code:0  否,返回 code:1 {}
      

    2. bind_toy 创建玩具并绑定玩具,双方建立关系

    1. 玩具添加app

      前端返回的数据是, 玩具的信息,以及对app的称呼,device_key,以及user_id
      
      根据设计好数据结构,补充其他key. 并且把多余的user_id pop出去, bind_user = user_id = toy_info.pop('user_id')  # app
      
      user_info = USer.find_one('_id:'ObjectId(user_id))	# 获取User_info信息
      char_id = Chat.insert_one({'user_list':[], 'chat_list':[]})	# 新建Chat表
      
      'friend_list' 的添加 : 
      toy_add_user = { 	# 填写朋友的信息 id  nick  remark  ava  type  
      	... friend_chat = str(chat_id.inserted_id);
      }
      然后,把 toy_add_u添加到 'friend_list'中, 再把toy_info 添加到数据库Toys (insert_one)(toy_info = 请求的dict())	
      
    2. app添加玩具

       user_add_toy = {
       	id =str( toy.insert)
       	frined_id = str(chat_id.insert)	# 一个聊天室
       }
      bind_toy 之前为空,也给他 str(toy.insert)
      把user_add_toy加入friend_list
      更新User,更新Chats   update_one user_list : [user_id,str(toy)]
      

    3. toy_list 获取玩具的列表

    • 通过后端的id获得toy列表,然后传给前端显示

    4. WebToy WebSocket连接 并保持连接

    1. 安装gevent-websocket 导入 geventwebsocket 
      

      appsocket

      app_socket = request.environ.get('wsgi.websocket')	# type:WebSocket  # 建立一个app连接
      如果有此链接,以toy为key,app_socket为value存入字典
      if app_socket:	# user_id 比如=7 to_user =4
      	user_socket_dict[user_id] = app_socket
      while True: 	
      	app_socket.receive() #其实是玩具在receive
      	
      	# 然后app发送,用的toy_socket 
      	
      	to_user = toy_data_dict.get('to_user')	# 
      	usocket = user_socket_dict.get(to_user)	# 只有当to_user (4)存在,即usock
      	user_socket_dict.get(to_user).send 上面的信息()		 # app_data是app向toy发送的信息
      

      app_data的信息 : send(app_data) 发送到哪了?按说是前端?

      {'chat': 'aa6ded85-387b-432e-bace-e4fb1b58097f.mp3', 'to_user': '5d36bf7d00c8bf23acf1a3f4', 'from_user': '5d36b6ab06eeb0fa0765c0f7'}
      
    2. toy也是这么连接

      @ws_app.route("/toy/<toy_id>")
      def toy(toy_id): # Toy 连接的位置
          print('toy_id', toy_id)
          print('1')
          toy_socket = request.environ.get("wsgi.websocket")  # type:WebSocket
          if toy_socket:
              user_socket_dict[toy_id] = toy_socket     # f4 = ts
          while True:
              toy_data = toy_socket.receive()    # f4 ts(app)
      
              toy_data_dict = json.loads(toy_data)
              print(toy_data_dict,'toy_data_dict')    # to_user': '5d36b6ab06eeb0fa0765c0f7'
              to_user = toy_data_dict.get("to_user")  # f7
              usocket = user_socket_dict.get(to_user)  # app_socket  玩具
              usocket.send(toy_data)  # app_socket (toy_data)	#向app发送信息
      
      

      send发送到前端哪里了?

    5. App WebSocket连接 并保持连接

    ​ while receiver() 一直夯在这里,但是只有一个

    6. App 向玩具发送音乐

    • 用的ws app_data

      {'to_user': '5d36bf7d00c8bf23acf1a3f4', 'music': 'c6b68f04-9a4c-46b6-9560-0bb31c38c7b7.mp3'} app_data_dict
      to_user 5d36bf7d00c8bf23acf1a3f4
      

      怎么接收到的? # (不是之后的逻辑app_uploader或者是toy_uploader)recv_msg

    第三天

    1. get_qr 获取QRCODE图片

    • 和get_xxx逻辑一样 send_file

    2. friend_list 查询好友列表

    1. 通过"_id"传过来的值,查找Users
      然后找Users的friend_list
      返回code:0 data:friend_list
      

    3. chat_list 接口 查询聊天记录

    1. 把上面的Users换成Chat friend_list换成chat_list

    4.app_uploader App上传语音消息

    1. 前端点击按住,然后松开,保存信息到了reco_file=request.files.get('reco_file')里

    2. 拼接文件夹,save一下. reco_file.save(reco_file_path) #保存成 amr

    3. os.system(f'ffmpeg -i {reco_file_path} {reco_file_path}.mp3')	# 转成MP3格式
      
    4. 根据id获得friend以及remark

      wenjianming = text2audio(f'你有来自{friend_remark}的消息')

    5. 给chat_info = {'f_u':re.fo.get('user_id'),

      't_u':re.fo.get('to_user'),

      'chat':f'{reco_file.filename}.mp3',

      'createTime':time.time()}

    6. 添加到数据库Chats里,之前新建的,所以现在update_one({},{'push':{'chat_list':chat_i}})

    7. 给玩具提示信息:

      RET["DATA"] = {
          'filename': wenjianming,
          'file_type': 'app'
      }
      

    5.toy_uploader Toy上传语音消息

    ​ 基本与上面同

    1. 录制信息reco_file=request.files.get('reco_file')

      filename = f"{uuid4()}.wav"
      reco_file_path = os.path.join(CHAT_PATH, filename)   # 怎么写入wav里的  默认写入吗
      reco_file.save(reco_file_path)	# 保存文件到拼接成的wav   
      
    2. 给chat_info = {

      "from_user": from_user,
      "to_user": to_user,
      "chat": filename,
      "createTime": time.time()}
      并加到Chats里	update_one如上面app_uploader
      
    3. 如果是toy发送过来的需要一个语音提醒

      type= request.form.get('friend_type')	
      	if friend_type = 'toy': filename = get_xxtx(to_user,form_user,'xxtx') #语音提醒函数
      

      并传过filename

    6.你有来自XXX(好友的备注)的消息

    1. friend_remark = '未知用户'
      def (to_user,from_user,tx_type=None):# type:不同场合,可给赋值,后面判断用
      	for循环friend_list列表,
      	if friend.get("friend_id") == from_user: 得出friend_remark
      wenjianming = text2audio(f'你有来自{friend_remark}的消息')
      return wenjianming
      

    第四天

    1.recv_msg 接收未读消息 多条消息连续收取

    1. 写set_redis# 存储未读消息

      这样的数据结构存储:离线未读消息
      {
          "user_id":{
              "from_id1":1,
              "from_id2":6,
          }
      }
      

      程序逻辑

      to_user_json = RDB.get(to_user)通过获得{}
      然后,如果if from_id有则+1 , 如果没有=1 
      好友第一次发,else: to_user_json = json.dumps({from_user:1})
      RDB.set(to_user,to_user_json)
      

      为什么用redis数据库呢? 快,非关系型数据库,内存级别(存储的信息,一时用)

    2. get_redis #获取单个用户的未读消息

      to_user_json = RDB.get(to_user)
      if to_user_json:	清空	先loads,然后count=pop,然后在dumps
      else: to_user_json = dumps({from_user:0})
      RDB.set(to_user, to_user_json)	
      return count
      
    3. 写recv_msg函数

      最后效果是传过去,你有来自谁的几条信息

      count=get_redis	#几条
      来自谁: wenjianming = get_xxtx()
      if count ==0 : wenjianming = text2audio(f'你没有信息')	
      	return {'chat_list':caht_info_list(把格式对齐传过去)}
      ret = {from_user, friend_type, 'chat_list'= 上面那样的}
      

      这里需要重写get_xxtx,来获得friend_type,然他返回俩个值

       if friend.get("friend_id") == from_user:
                  friend_remark = friend.get('friend_remark')
                  friend_type = friend.get('friend_type')  
                  wenjianming = text2audio(f'以下是来自{friend_remark}的消息')
              	return wenjianming, friend_type
      

      count,friend_type = get_xxtx(,,None) #那边其实有判断的,提醒一下了

    2. BaiduAI TTS 语音合成 实现消息提醒

    ​ "以下是来自xxx的消息"

    • 程序如下:

      def text2audio(A):
          res = SPEECH_CLIENT.synthesis(A, "zh", 1, VIOCE)
          file_name = f"{uuid4()}.mp3"
      
          file_path = os.path.join(CHAT_PATH, file_name)
          if type(res) == dict:
              pass
          with open(file_path, "wb") as f:
              f.write(res)
      
          return file_name
      

    3. ai_uploader 处理Toy的语音指令

    • ai_uploader()

      将保存的录音存储成MP3,然后通过a2t转换成文字,
      传到my_nlp_low进行处理
      
    • my_nlp_low(Q,toy_id):

      if '我要听' in Q : 
      	return {"from_user": "ai", "music": content.get('music')}
      if '发消息' in Q:
      	for循环好友列表,remark return {'chat' :   filename = text2audio(f'可以给{remark}发')}
      else:
      	A = go_tl(Q) #图灵机器人的回答
      	filename = text2audio(A)  return 返回
      

      music:里的content = my_nlp(Q) # 用到了机器学习gensim的知识,判断歌名相似度

      另一种方法是:

      for content in MDB.Content.find({}) #从数据库里找歌名 完全匹配

      ​ 如果和Q相等,则返回

    4.BaiduAI ASR 语音识别 实现Toy语音指令 NLP 自然语言处理

    ​ 上面就用到了是吧

    第五天

    1. add_req 添加好友请求

    • 判断add_type == 'toy'  :user_info =Toy.find_
      	else: User.find_one()
      req["nickname"] = user_info.get('nickname') if user_info.get('nickname') else user_info.get('toy_name')	  #这种写法
      req['status'] =0 同意
      MDB.Request.insert_one(req) #写到Request数据表
      
    • 拒绝好友

      reqid = request.form.get('req_id')
      MDB.Request.update_one({'_id': ObjectId(reqid)}, {'$set': {'status': 2}})
      

    2. req_list 查看当前App所绑定的Toy收到的好友请求

    循环列表套字典改值颠覆认知
    a = [{'a': 1}, {'a': 2}]
    for i in a:
        i['a'] = 0
    print(a)
    结果: [{'a': 0}, {'a': 0}]
    

    程序

    add_req_list = list(MDB.Request.find({'toy_id': {"$in": bind_toys}, 'status': 0}))  #
    for item in add_req_list:
    	item['_id'] = str(item.get('_id'))
    RET['DATA'] = add_req_list
    

    3. acc_req接收好友请求

    ​ 获得toy user req

    • user添加toy

      然后 user_add_toy = {id , nick ,remark , avatar, chat , type}
      更新  Users/Toys
       if req.get('add_type') != 'toy':Users.updat/Toy.update
      
      if add_type == 'toy': MDB.Toys.find_one()/MDB.Users.find_one()
      
      
    • toy_add_user

        MDB.Request.update_one
        MDB.Toys.update_one
      
  • 相关阅读:
    @Aspect 注解使用详解
    Mysql的4个隔离级别
    【学习笔记】二分类问题中的“最大似然”与“交叉熵损失”概念的理解
    【转】对“先验概率”与“后验概率”概念的通俗理解
    nginx——安装部署vue项目
    JWT
    Vue——自定义组件实现vmodel
    Vue——子级向父级传递参数
    SpringBoot2(十四)全局异常切面
    Vue——ElementUI表格分页
  • 原文地址:https://www.cnblogs.com/Doner/p/11948807.html
Copyright © 2011-2022 走看看