开发者日志

第一天

智能玩具开发者日志

新学的快捷键: 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
    
posted @ 2019-07-30 23:21  learnacode  阅读(196)  评论(0编辑  收藏  举报