智能玩具 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()

 

posted @ 2019-07-23 20:53  我的IT007  阅读(399)  评论(0编辑  收藏  举报