zoukankan      html  css  js  c++  java
  • 智能玩具 WebSocket通讯 好友列表 聊天列表

    项目 智能玩具


    一、需求分析
    1外形美观大方
    2功能:1语音的实时通讯
    2积极正面内容
    -播放音频(播放 父母选定的儿歌,故事,百科,英语)
    -语音识别 (通过语音识别内容名称 玩具可以主动点播内容)
    3陪孩子聊天
    4解答问题(十万个为什么)
    5家长通过玩具查看社交圈

    二、具体实施
    第一天:
    获取音频资源
    1从喜马拉雅采集幼教内容,存入文件
    分别获取封面/音乐 文件
    将数据写入数据库

    app 获取内容 /content_list
    -信息以列表的形式返回

    接口功能实现
    根据前端的需求返回相应的数据
    App /get_cover 获取内容的图片信息
    App /get_music 获取音频信息


    2用户的注册 、登录 、自动登录
    App /reg 注册用户
    App /login 用户登录 返回的用户信息
    App /auto_login 用户打开APP后自动登录 返回的用户信息

    3创建设备的DeviceKey(联图网创建二维码)
    保证唯一性
    -hashlib.md5((f"{uuid4()}{time.time()}{uuid4()}".encode("utf8")).hexdigest()

    第二天:
    App 绑定一个设备 扫描二维码,设备必须有一个符合我们数据库中的二维码
    设备 一旦和App进行绑定 由App创建玩具

    1扫码
    通过 {device_key:""} 去数据库中查找 是否有该二维码信息

    1.二维码扫描成功并且设备未进行绑定
    2.二维码扫描失败,扫描的条码不是设备库中存在的

    3.二维码扫描成功, 但设备已经进行绑定
    (还未实现)

    2绑定玩具
    按照数据库要求 构建玩具的基本信息

    先创建一个空的Chats 表
    -chat_id = MDB.Chats.insert_one({"user_list": [], "chat_list": []})


    1创建toy (结合数据库结构和API文档,获取信息)
    toy 绑定 user
    先给toy 添加第一个好友 app

    注意 friend_chat 的写法
    - "friend_chat": str(chat_id.inserted_id)


    追加
    -toy_info["friend_list"].append(toy_add_user)
    toy_id = MDB.Toys.insert_one(toy_info)

    2.User表数据补充
    app 也要同时 增加toy为好友

    user_add_toy = {
    "friend_id": toy_id.inserted_id, # toy_id str
    "friend_nick": toy_info.get("baby_name"), # baby_name
    "friend_remark": toy_info.get("toy_name"), # toy_name
    "friend_avatar": "toy.jpg", #
    "friend_chat": str(chat_id.inserted_id), # chat_id
    "friend_type": "toy" # 好友的类型 toy
    }

    添加到表结构中
    user_info["bind_toys"].append(str(toy_id.inserted_id))
    user_info["friend_list"].append(user_add_toy)

    整体修改数据
    # 修改 Users 的全部数据
    MDB.Users.update_one({"_id": ObjectId(user_id)}, {"$set": user_info})

    # Chats 数据也会变化 user_list 将 toy_id 和 user_id 加入
    MDB.Chats.update_one({"_id":chat_id.inserted_id}, {"$set": {"user_list": [user_id,str(toy_id.inserted_id)]}})


    数据结构

    3 toy_list 展示
    从toys 表中查找对应数据,返回(参考表中的数据)

    第三天:
    1 智能玩具WebSocket通讯
    Websocket 连接 OpenToy 开机
    按照格式 开启wevbsocket

    解决跨域问题
    App通讯 向toy 发送音乐
    ws://10.0.0.1:9528/app/<user_id>
    Toys通讯 接收App推送音乐
    ws://10.0.0.1:9528/toy/<toy_id>

    1 /get_qr 接口 获取QRCODE 图片
    -获取图片/音乐/二维码图片等原理是相通的
    2 /friend_list 查询好友列表

    3 /chat_list 查询聊天记录

    4 /app_uploader app 上传语音消息

    5 /toy_uploader toy 上传语音消息


    注意事项:
    前端发送请求所携带的数据 和后端响应的数据

    app/toy 上传语音消息 注意 文件格式的转化
    跨域问题的解决(安装包)

    获取数据--保存文件--转化格式--聊天记录--更新聊天记录--返回RET

    /get_qr 接口

    # 返回二维码信息图片
    @content_bp.route("/get_qr/<filename>",methods=["GET"])
    def get_qr(filename):
        qr_path=os.path.join(QRCODE_PATH,filename)
        return send_file(qr_path)

     /friend_list 接口          /chat_list 接口

    from bson import ObjectId
    from flask import Blueprint, request, jsonify
    
    from settings import MDB, RET
    
    friend_bp = Blueprint("friend_bp", __name__)
    
    
    @friend_bp.route("/friend_list", methods=["POST"])
    def friend_list():
        user_id = request.form.get("_id")
        user_info = MDB.Users.find_one({"_id": ObjectId(user_id)})
    
        RET["CODE"] = 0
        RET["MSG"] = "好友查询"
        RET["DATA"] = user_info.get("friend_list")
    
        print(user_info, "+++++++++")
        return jsonify(RET)
    
    
    @friend_bp.route("/chat_list", methods=["POST"])
    def chat_list():
        chat = request.form.to_dict()
        chat_window = MDB.Chats.find_one({"_id": ObjectId(chat.get("chat_id"))})
    
        RET["CODE"] = 0
        RET["MSG"] = "查询聊天记录"
        RET["DATA"] = chat_window.get("chat_list")
    
        return jsonify(RET)

    实现 /app_uploader 接口 App上传语音消息
    实现 /toy_uploader 接口 Toy上传语音消息

    import os
    import time
    
    from bson import ObjectId
    from flask import Blueprint, request, jsonify
    
    from settings import MDB, RET, CHAT_PATH
    
    uploader_bp = Blueprint("uploader_bp", __name__)
    
    
    @uploader_bp.route("/app_uploader", methods=["POST"])
    def app_uploader():
        to_user = request.form.get("to_user")
        from_user = request.form.get("user_id")
        reco_file = request.files.get("reco_file")
    
        reco_file_path = os.path.join(CHAT_PATH, reco_file.filename)
        # 保存的文件格式为amr
        reco_file.save(reco_file_path)
        # 转化格式
        os.system(f"ffmpeg -i {reco_file_path} {reco_file_path}.mp3")
    
        user_list = [to_user, from_user]
        # 聊天信息记录
        chat_info = {
            "from_user": from_user,
            "to_user": to_user,
            "chat": f"{reco_file.filename}.mp3",
            "createTime": time.time()
        }
        # 更新聊天数据
        MDB.Chats.update_one({"user_list": {"$all": user_list}}, {"$push": {"chat_list": chat_info}})
    
        RET["CODE"] = 0
        RET["MSG"] = "上传成功"
        RET["DATA"] = {
            "filename": f"{reco_file.filename}.mp3",
            "friend_type": "app"
        }
        return jsonify(RET)
    
    
    from uuid import uuid4
    
    
    @uploader_bp.route("/toy_uploader", methods=["POST"])
    def toy_uploader():
        to_user = request.form.get("to_user")
        from_user = request.form.get("user_id")
        reco_file = request.files.get("reco")
         # 与app_uploader 不同    文件名   blob   reco_file.filename  是文件类型
        # print(reco_file.filename, "++++++")
    
        filename = f"{uuid4()}.wav"
        reco_file_path = os.path.join(CHAT_PATH, filename)
    
        reco_file.save(reco_file_path)
    
        user_list = [to_user, from_user]
        # 聊天信息记录
        chat_info = {
            "from_user": from_user,
            "to_user": to_user,
            "chat": filename,
            "createTime": time.time()
        }
        # 更新聊天数据
        MDB.Chats.update_one({"user_list": {"$all": user_list}}, {"$push": {"chat_list": chat_info}})
    
        RET["CODE"] = 0
        RET["MSG"] = "上传成功"
        RET["DATA"] = {
            "filename": filename,
            "friend_type": "toy"
        }
        return jsonify(RET)

     wap_ws   websocket 连接

    import json
    from flask import Flask, request, render_template
    
    from geventwebsocket.handler import WebSocketHandler
    
    from geventwebsocket.server import WSGIServer
    
    from geventwebsocket.websocket import WebSocket
    
    ws_app = Flask(__name__)
    user_socket_dict = {}
    
    
    # 建立websocket连接
    @ws_app.route("/app/<user_id>")
    def app(user_id):
        # print(user_id,"user_id")
        # 获得wesocket 连接
        app_socket = request.environ.get("wsgi.websocket")  # type: WebSocket
        if app_socket:
            user_socket_dict[user_id] = app_socket
    
        while True:
            app_data = app_socket.receive()
            app_data_dict = json.loads(app_data)
            to_user = app_data_dict.get("to_user")
            usocket = user_socket_dict.get(to_user)
            try:
                usocket.send(app_data)
            except:
                continue
    
    
    @ws_app.route("/toy/<toy_id>")
    def toy(toy_id):
        # 获得wesocket 连接
        toy_socket = request.environ.get("wsgi.websocket")  # type: WebSocket
        if toy_socket:
            user_socket_dict[toy_id] = toy_socket
    
        while True:
            toy_data = toy_socket.receive()
            toy_data_dict = json.loads(toy_data)
            to_user = toy_data_dict.get("to_user")
            usocket = user_socket_dict.get(to_user)
            # usocket.send(toy_data)
            try:
                usocket.send(toy_data)
            except:
                continue
    
    
    @ws_app.route("/get_toy")
    def get_toy():
        return render_template("WebToy.html")
    
    
    if __name__ == '__main__':
        http_serve = WSGIServer(("0.0.0.0", 9528), ws_app, handler_class=WebSocketHandler)
        http_serve.serve_forever()
  • 相关阅读:
    测光
    闪光灯
    快门
    光圈
    白加黑减
    曝光补偿
    取景雷区
    着眼点
    Web中的无状态含义
    图计算模型[转]
  • 原文地址:https://www.cnblogs.com/XLHIT/p/11234397.html
Copyright © 2011-2022 走看看