人工智能-树莓派小车(5)——用微信控制智能小车

之前所做的有一个特点就是需要在树莓派上连接一个USB麦克风,通过这个麦克风来进行语音的输入,但是在实际使用场景上来看,这是不合理的,因此需要一个可以远程操控智能小车的方案,因此萌发了将控制端移植到手机上的想法,移植到手机上也有几个不同的方案。

  1. 通过Zigbee无线传输技术进行数据的传输
    优点:易于进行扩展,可方便的与其他智能家居连接起来
    缺点:传输的数据量很小,不适用于语音数据以及图像数据的传递
  2. 通过搭建一个服务器,开发一个手机APP,通过服务器进行数据的传输
    优点:自己搭建服务器, 可控制性强
    缺点:开发门槛高(需要进行服务器的搭建以及手机应用的开发,不易实现)以及使用门槛高(需要单独在手机上安装一个APP)
  3. 通过微信平台,进行数据(文本、语音、图像、视频)的传递
    优点:人人都有微信,使用门槛低,功能相对全面
    缺点:可控制性相对较弱

最终经过权衡,选取第三个方案,通过微信控制智能小车。

itchat

itchat是一个开源的微信个人号接口,使用python调用微信从未如此简单。可以通过它进行微信消息的读取,回复,联系人的读取等等

1. 安装

pip install itchat

2. 简单入门

1.登陆配置

登陆使用的是itchat提供了auto_login方法,调用即可完成登录。
一般而言,会在完成消息的注册之后再进行登陆。
这里需要特别强调的是两点,分别是短时间关闭重连命令行二维码

  • itchat提供了登陆状态暂存,关闭程序后一定时间内不需要扫码即可登录。由于目前微信网页版提供上一次登录的微信号不扫码直接手机确认登陆,所以如果开启登陆状态暂存将会自动使用这一功能。
  • 为了方便在无图形界面使用itchat,程序内置了命令行二维码的显示。
短时间关闭程序后重连

这样即使程序关闭,一定时间内重新开启也可以不用重新扫码。
最简单的用法就是给auto_login方法传入值为真的hotReload。
该方法会生成一个静态文件itchat.pkl,用于存储登陆的状态。

import itchat
from itchat.content import TEXT

@itchat.msg_register(TEXT)
def simple_reply(msg):
    print(msg.text)

itchat.auto_login(hotReload=True)
itchat.run()
命令行二维码显示

通过以下命令可以在登陆的时候使用命令行显示二维码:

itchat.auto_login(enableCmdQR=True)

部分系统可能字幅宽度有出入,可以通过将enableCmdQR赋值为特定的倍数进行调整:如部分的linux系统,块字符的宽度为一个字符(正常应为两字符),故赋值为2

itchat.auto_login(enableCmdQR=2)

2.聊天对象

在使用个人微信的过程当中主要有三种账号需要获取,分别为:

  • 好友
  • 公众号
  • 群聊

itchat为这三种账号都提供了整体获取方法与搜索方法。群聊多出获取用户列表方法以及创建群聊、增加、删除用户的方法
接下来对三种分别介绍如何使用以及如何通过唯一的Uin确定好友与群聊。

好友

好友的获取方法为get_friends,将会返回完整的好友列表。

  • 其中每个好友为一个字典
  • 列表的第一项为本人的账号信息
  • 传入update键为True将可以更新好友列表并返回

好友的搜索方法为search_friends,有四种搜索方式:

  1. 仅获取自己的用户信息
  2. 获取特定UserName的用户信息
  3. 获取备注、微信号、昵称中的任何一项等于name键值的用户
  4. 获取备注、微信号、昵称分别等于相应键值的用户

下面是示例程序:

获取自己的用户信息,返回自己的属性字典

itchat.search_friends()

获取特定UserName的用户信息

itchat.search_friends(userName='@abcdefg1234567')

获取任何一项等于name键值的用户

itchat.search_friends(name='littlecodersh')

获取分别对应相应键值的用户

itchat.search_friends(wechatAccount='littlecodersh')

其中3、4项功能可以一同使用,将返回同时满足两个条件的好友

itchat.search_friends(name='LittleCoder机器人', wechatAccount='littlecodersh')

更新用户信息的方法为update_friend。

  • 该方法需要传入用户的UserName,返回指定用户的最新信息
  • 也可以传入UserName组成的列表,那么相应的也会返回指定用户的最新信息组成的列表
memberList = itchat.update_friend('@abcdefg1234567')
公众号

公众号的获取方法为get_mps,将会返回完整的公众号列表。

  • 其中每个公众号为一个字典
  • 传入update键为True将可以更新公众号列表并返回

公众号的搜索方法为search_mps,有两种搜索方法:

  1. 获取特定UserName的公众号
  2. 获取名字中含有特定字符的公众号

如果两项都做了特定,将会仅返回特定UserName的公众号,下面是示例程序:

获取特定UserName的公众号,返回值为一个字典

itchat.search_mps(userName='@abcdefg1234567')

获取名字中含有特定字符的公众号,返回值为一个字典的列表

itchat.search_mps(name='LittleCoder')

以下方法相当于仅特定了UserName

itchat.search_mps(userName='@abcdefg1234567', name='LittleCoder')
群聊

群聊的获取方法为get_chatrooms,将会返回完整的群聊列表。

  • 其中每个群聊为一个字典
  • 传入update键为True将可以更新群聊列表并返回通讯录中保存的群聊列表
  • 群聊列表为后台自动更新,如果中途意外退出存在极小的概率产生本地群聊消息与后台不同步
  • 为了保证群聊信息在热启动中可以被正确的加载,即使不需要持续在线的程序也需要运行itchat.run()
  • 如果不想要运行上述命令,请在退出程序前调用itchat.dump_login_status(),更新热拔插需要的信息

群聊的搜索方法为search_chatrooms,有两种搜索方法:

  1. 获取特定UserName的群聊
  2. 获取名字中含有特定字符的群聊

如果两项都做了特定,将会仅返回特定UserName的群聊,下面是示例程序:

获取特定UserName的群聊,返回值为一个字典

itchat.search_chatrooms(userName='@@abcdefg1234567')

获取名字中含有特定字符的群聊,返回值为一个字典的列表

itchat.search_chatrooms(name='LittleCoder')

以下方法相当于仅特定了UserName

itchat.search_chatrooms(userName='@@abcdefg1234567', name='LittleCoder')

群聊用户列表的获取方法为update_chatroom。

  • 如果想要更新该群聊的其他信息也可以用该方法
  • 群聊在首次获取中不会获取群聊的用户列表,需要调用该命令才能获取群聊的成员
  • 该方法需要传入群聊的UserName,返回特定群聊的详细信息
  • 也可以传入UserName组成的列表,那么相应的也会返回指定用户的最新信息组成的列表
memberList = itchat.update_chatroom('@@abcdefg1234567', detailedMember=True)

创建群聊、增加、删除群聊用户的方法如下所示:

  • 由于之前通过群聊检测是否被好友拉黑的程序,目前这三个方法都被严格限制了使用频率
  • 删除群聊需要本账号为群管理员,否则会失败
  • 将用户加入群聊有直接加入与发送邀请,通过useInvitation设置
  • 超过40人的群聊无法使用直接加入的加入方式,特别注意
memberList = itchat.get_friends()[1:]
chatroomUserName = itchat.create_chatroom(memberList, 'test chatroom') # 创建群聊,topic键值为群聊名
itchat.delete_member_from_chatroom(chatroomUserName, memberList[0]) # 删除群聊内的用户
itchat.add_member_into_chatroom(chatroomUserName, memberList[0], useInvitation=False) # 增加用户进入群聊
Uins

Uin 就是微信中用于标识用户的方式,每一个用户、群聊都有唯一且不同的Uin。通过Uin,即使退出了重新登录,也可以轻松的确认正在对话的是上一次登陆的哪一个用户。但注意,Uin与其他值不同,微信后台做了一定的限制,必须通过特殊的操作才能获取。
最简单来说,首次点开登陆用的手机端的某个好友或者群聊,itchat就能获取到该好友或者群聊的Uin。
如果想要通过程序获取,也可以用程序将某个好友或者群聊置顶(取消置顶)。
这里提供一个提示群聊更新的程序:

import re, sys, json

import itchat
from itchat.content import *

itchat.auto_login(True)

@itchat.msg_register(SYSTEM)
def get_uin(msg):
    if msg['SystemInfo'] != 'uins': return
    ins = itchat.instanceList[0]
    fullContact = ins.memberList + ins.chatroomList + ins.mpList
    print('** Uin Updated **')
    for username in msg['Text']:
        member = itchat.utils.search_dict_list(
            fullContact, 'UserName', username)
        print(('%s: %s' % (
            member.get('NickName', ''), member['Uin']))
            .encode(sys.stdin.encoding, 'replace'))

itchat.run(True)

每当Uin更新了,就会打印相应的更新情况。

3.消息处理

消息内容

微信初始化消息、文本消息、图片消息、小视频消息、地理位置消息、名片消息、语音消息、动画表情、普通链接或应用分享消息、音乐链接消息、群消息、红包消息、系统消息

回复方法
  • 方法:
send(msg='Text Message', toUserName=None)
  • 所需值:
    • msg:消息内容
    • '@fil@文件地址'将会被识别为传送文件
    • '@img@图片地址'将会被识别为传送图片
    • '@vid@视频地址'将会被识别为小视频
    • toUserName:发送对象,如果留空将会发送给自己
  • 返回值:发送成功->True, 失败->False
  • 程序示例:使用的素材可以在这里下载
#coding=utf8
import itchat

itchat.auto_login()
itchat.send('Hello world!')
# 请确保该程序目录下存在:gz.gif以及xlsx.xlsx
itchat.send('@img@%s' % 'gz.gif')
itchat.send('@fil@%s' % 'xlsx.xlsx')
itchat.send('@vid@%s' % 'demo.mp4')

4.注册方法

itchat将根据接收到的消息类型寻找对应的已经注册的方法。如果一个消息类型没有对应的注册方法,该消息将会被舍弃。

注册

可以通过两种方式注册消息方法

import itchat
from itchat.content import *

# 不带具体对象注册,将注册为普通消息的回复方法
@itchat.msg_register(TEXT)
def simple_reply(msg):
    return 'I received: %s' % msg['Text']

# 带对象参数注册,对应消息对象将调用该方法
@itchat.msg_register(TEXT, isFriendChat=True, isGroupChat=True, isMpChat=True)
def text_reply(msg):
    msg.user.send('%s: %s' % (msg.type, msg.text))
消息类型

向注册方法传入的msg包含微信返回的字典的所有内容。

本api增加Text、Type(也就是参数)键值,方便操作。

itchat.content中包含所有的消息类型参数,内容如下表所示:

参数 类型 Text键值
TEXT 文本 文本内容
MAP 地图 位置文本
CARD 名片 推荐人字典
NOTE 通知 通知文本
SHARING 分享 分享名称
PICTURE 图片/表情 下载方法
RECORDING 语音 下载方法
ATTACHMENT 附件 下载方法
VIDEO 小视频 下载方法
FRIENDS 好友邀请 添加好友所需参数
SYSTEM 系统消息 更新内容的用户或群聊的UserName组成的列表

比如你需要存储发送给你的附件:

@itchat.msg_register(ATTACHMENT)
def download_files(msg):
    msg['Text'](msg['FileName'])

值得注意的是,群消息增加了三个键值:

  • isAt: 判断是否@本号
  • ActualNickName: 实际NickName
  • Content: 实际Content

可以通过本程序测试:

import itchat
from itchat.content import TEXT

@itchat.msg_register(TEXT, isGroupChat=True)
def text_reply(msg):
    print(msg.isAt)
    print(msg.actualNickName)
    print(msg.text)

itchat.auto_login()
itchat.run()
注册消息的优先级

优先级分别为:后注册消息先于先注册消息,带参数消息先于不带参数消息。

以下面的两个程序为例:

import itchat
from itchat.content import *

itchat.auto_login()

@itchat.msg_register(TEXT)
def text_reply(msg):
    return 'This is the old register'

@itchat.msg_register(TEXT)
def text_reply(msg):
    return 'This is a new one'

itchat.run()

在私聊发送文本时将会回复This is a new one。

import itchat
from itchat.content import *

itchat.auto_login()

@itchat.msg_register
def general_reply(msg):
    return 'I received a %s' % msg.type

@itchat.msg_register(TEXT)
def text_reply(msg):
    return 'You said to me one to one: %s' % msg.text

itchat.run()

仅在私聊发送文本时将会回复You said to me one to one,其余情况将会回复I received a ...。

STT (Speak To Text)

通过上述的itchat模块,就可以在树莓派上用python进行微信的信息接收等,文本消息我们可以利用之前类似的方法进行识别、控制,那么仅仅用文本消息控制就显得不够智能了,需要用语音来控制,那么如何用语音来控制小车呢?这就要用到STT模块,这个模块做的就是把语音识别为文本信息,目前有多家公司有开源项目可以使用,比如Google、百度、讯飞,综合考虑语音识别准确率、易用性上,我选择了百度的API接口。

百度AI平台

要想使用百度的语音识别API,有如下几个准备工作。

  1. 首先要成为百度开发者
  2. 创建应用
  3. 获取密钥
  4. 合成Access Token

前三部分可以在百度开发者平台上很简单的注册申请,不再赘述。要注意的是保留好上述申请到的密钥(API KEY、Secret KEY),会在下面用到;第四部分下面会详细介绍。

语音识别简介

百度语音识别通过 REST API 的方式给开发者提供一个通用的 HTTP 接口。 上传需要完整的录音文件,录音文件时长不超过60s。

调用流程

1. 获取Access Token

请求URL数据格式
向授权服务地址https://aip.baidubce.com/oauth/2.0/token发送请求(推荐使用POST),并在URL中带上以下参数:

  • grant_type: 必须参数,固定为client_credentials;
  • client_id: 必须参数,应用的API Key;
  • client_secret: 必须参数,应用的Secret Key;

Python获取access_token示例代码

import urllib, urllib2, sys
import ssl

# client_id 为官网获取的AK, client_secret 为官网获取的SK
host = 'https://aip.baidubce.com/oauth/2.0/token?grant_type=client_credentials&client_id=【官网获取的AK】&client_secret=【官网获取的SK】'
request = urllib2.Request(host)
request.add_header('Content-Type', 'application/json; charset=UTF-8')
response = urllib2.urlopen(request)
content= response.read()
if (content):
    print(content)

上述代码中content是一个JSON格式信息,其中包含你请求到的授权码,会在调用API时用到,有限期一般为一个月。
服务器返回的JSON文本参数如下

  • access_token: 要获取的Access Token;
  • expires_in: Access Token的有效期(秒为单位,一般为1个月);
  • 其他参数忽略,暂时不用;
    例如:
{
  "access_token": "25.b55fe1d287227ca97aab219bb249b8ab.315360000.1798284651.282335-8574074",
  "expires_in": 2592000,
  "scope": "public wise_adapt",
  "session_key": "9mzdDZXu3dENdFZQurfg0Vz8slgSgvvOAUebNFzyzcpQ5EnbxbF+hfG9DQkpUVQdh4p6HbQcAiz5RmuBAja1JJGgIdJI",
  "access_token": "24.6c5e1ff107f0e8bcef8c46d3424a0e78.2592000.1485516651.282335-8574074",
  "session_secret": "dfac94a3489fe9fca7c3221cbf7525ff"
}

其中access_token即为我们需要的信息,通过Python的json模块,把它提取出来。

data = json.loads(content)
token = data["access_token"]
2. 请求方式
  • 如果音频在本地,需要将音频数据放在body中。(推荐方式)
  • 如果音频在互联网上,可以让百度服务器下载,然后回调到自己服务器的接口
  • 音频在本地,有JSON和raw两种方式提交。
  • 音频在在互联网上,需要百度服务器下载,只能通过JSON方式提交

这里只介绍通过json 方式,上传本地文件(官方推荐,更高效)

JSON方式上传

语音数据和其他参数通过标准 JSON 格式串行化 POST 上传, JSON 里包括的参数:

字段名 是必填或选填 描述
format 必填 语音文件的格式,pcm 或者 wav 或者 amr。不区分大小写。推荐pcm文件
rate 必填 采样率, 8000 或者 16000, 推荐 16000 采用率
channel 必填 声道数,仅支持单声道,请填写固定值 1
cuid 必填 用户唯一标识,用来区分用户,计算UV值。建议填写能区分用户的机器 MAC 地址或 IMEI 码,长度为60字符以内。
token 必填 开放平台获取到的开发者[ access_token](http://yuyin.baidu.com/docs/tts/135#获取 Access Token "access_token")
lan 选填 语种选择,默认中文(zh)。 中文=zh、粤语=ct、英文=en,不区分大小写
url 选填 可下载的语音下载地址,与callback连一起使用,确保百度服务器可以访问。
callback 选填 用户服务器的识别结果回调地址,确保百度服务器可以访问
speech 选填 本地语音文件的的二进制语音数据 ,需要进行base64 编码。与len参数连一起使用。
len 选填 本地语音文件的的字节数,单位字节
上传示例(speech, len 参数)

JSON格式POST上传本地文件,固定头部header:Content-Type:application/json,4K大小的pcm文件(普通话录音)请求: speech 参数填写为文件内容base64后的结果:

{
    "format":"pcm",
    "rate":16000,
    "channel":1,
    "token":xxx,
    "cuid":"baidu_workshop",
    "len":4096,
    "speech":"xxx", // xxx为 base64(FILE_CONTENT)
}
返回示例
{
    "corpus_no":"6433214037620997779",
    "err_msg":"success.",
    "err_no":0,
    "result":["北京科技馆,"],
    "sn":"371191073711497849365"
}
注意事项
  • len 字段表示原始语音大小字节数,不是 base64 编码之后的长度。
核心代码
# -*- coding: utf-8 -*-
"""
语音识别功能模块(语音输入)
参考:http://open.duer.baidu.com/doc/dueros-conversational-service/device-interface/voice-input_markdown
"""

import urllib.request
import json
import base64


def listen(file):

    os.system('ffmpeg -y -i %s -acodec pcm_s16le -f s16le -ac 1 -ar 16000 16k_dai.pcm' % file)
    #打开音频文件,并进行编码
    f = open(WAVE_FILE, "rb")
    speech = base64.b64encode(f.read()).decode('utf-8')
    size = os.path.getsize(WAVE_FILE)
    update = json.dumps({"format":WAVE_TYPE, "rate":VOICE_RATE, 'channel':1,'cuid':USER_ID,'token':token,'speech':speech,'len':size}).encode('utf-8')
    update_length = len(update)
    headers = { 'Content-Type' : 'application/json' } 
    url = "http://vop.baidu.com/server_api"
    req = urllib.request.Request(url)
    req.add_header("Content-Type", "application/json")
    req.add_header("Content-Length", update_length)
    r = urllib.request.urlopen(url=req, data=update)
    t = r.read().decode('utf-8')
    result = json.loads(t)
    if result['err_msg']=='success.':
        command = result['result'][0].encode('utf-8').decode()
        return command
    else:
        return '我没有听懂你说什么!!!'

    
#设置应用信息
baidu_server = "https://openapi.baidu.com/oauth/2.0/token?"
grant_type = "client_credentials"
client_id = "*****************" #填写API Key   需自行申请
client_secret = "****************" #填写Secret Key

#合成请求token的URL
url = baidu_server+"grant_type="+grant_type+"&client_id="+client_id+"&client_secret="+client_secret

#获取token
res = urllib.request.urlopen(url).read().decode()
data = json.loads(res)
token = data["access_token"]
print ( token )

#设置音频属性,根据百度的要求,采样率必须为8000,压缩格式支持pcm(不压缩)、wav、opus、speex、amr
VOICE_RATE = 16000
WAVE_FILE = "16k_dai.pcm" #音频文件的路径
USER_ID = "hail_hydra" #用于标识的ID,可以随意设置
WAVE_TYPE = "pcm"

TTS(Text To Speak)

智能小车识别命令做出相应动作后要进行反馈,同样采用百度的语音合成API,将要说的话合称为语音,这部分我们采用与上面的REST API不同的方式,采用Python SDK的方式获取。

安装语音合成 Python SDK

语音合成 Python SDK目录结构

├── README.md
├── aip                   //SDK目录
│   ├── __init__.py       //导出类
│   ├── base.py           //aip基类
│   ├── http.py           //http请求
│   └── speech.py //语音合成
└── setup.py              //setuptools安装

安装使用Python SDK有如下方式:

  • 如果已安装pip,执行pip install baidu-aip即可。
  • 如果已安装setuptools,执行python setup.py install即可。

此种方式比较简单,不做详细介绍,直接上核心代码

核心代码

# -*- coding: utf-8-*-

import os
import sys
from imp import reload

reload(sys)

def say(what):
#配置账户信息

    from aip import AipSpeech
    """ 你的 APPID AK SK """
    APP_ID = '10462370'
    API_KEY = 
    SECRET_KEY = 
    client = AipSpeech(APP_ID, API_KEY, SECRET_KEY)

    result  = client.synthesis( what, 'zh', 1, {
        'vol': 5,
        'per': 3,
    })
    # 识别正确返回语音二进制 错误则返回dict 参照下面错误码
    if not isinstance(result, dict):
        with open('auido.mp3', 'wb') as f:
            f.write(result)
    os.system("auido.mp3")
    
if __name__ == '__main__':
    say('李博是最最最帅的')

控制代码

这部分在教程人工智能-树莓派小车(4)——通过语音玩转智能小车已经介绍过,原理相同,这里只放代码。

def recognize():

        file = '/home/pi/Rascar-DuerOS-Python-Client/ord.txt' # 读取文件
        f = open(file,'r')
        out = f.read()
        command = out.decode('unicode-escape').encode('utf-8')
        print command
        GPIO.output(LED_CTR, GPIO.LOW)
        ############################################
        ###############命令识别######################
        ############################################
        
       if command.find(u"开") !=-1 and command.find(u"大") !=-1 and command.find(u"灯") !=-1:
            print ("打开前大灯")
            say(random.choice(['已经帮您开灯','开灯了','好的,开灯','是,正在开灯']))
            robot.Open_Flight()
            GPIO.output(LED_CTR, GPIO.HIGH)
            
        elif command.find(u"关") !=-1 and command.find(u"大") !=-1 and command.find(u"灯") !=-1:
                print ("关闭前大灯")
                say(random.choice(['已经帮您关灯','关灯了','好的,关灯','是,正在关灯']))
                robot.Close_Flight()
                GPIO.output(LED_CTR, GPIO.HIGH)
                
        elif command.find(u"前") !=-1 and command.find(u"进") !=-1:
                print ("前进")
                say(random.choice(['好的,前进','向前出发','是,前进一步']))
                robot.Motor_Forward()
                time.sleep(2)
                robot.Motor_Stop()
                GPIO.output(LED_CTR, GPIO.HIGH)
                
        elif command.find(u"后") !=-1 and command.find(u"退") !=-1:
                print ("后退")
                say(random.choice(['好的,后退','倒车请注意','是,后退一点']))
                robot.Motor_Backward()
                time.sleep(2)
                robot.Motor_Stop()
                GPIO.output(LED_CTR, GPIO.HIGH)
                
        elif command.find(u"左") !=-1 and command.find(u"转") !=-1:
                print ("左转")
                say(random.choice(['好嘞,向左转','拐啦,拐啦,向左拐啦','好的,向左转弯','是,向左转弯']))
                robot.Motor_TurnLeft()
                p = GPIO.PWM(11, 3)
                p.start(20)
                time.sleep(0.5)
                p.stop()
                robot.Motor_Stop()
                GPIO.output(11, GPIO.LOW)
                GPIO.output(LED_CTR, GPIO.HIGH)
                
                
        elif command.find(u"右") !=-1 and command.find(u"转") !=-1:
                print ("右转")
                say(random.choice(['好嘞,向右转','拐啦,拐啦,向右拐啦','好的,向右转弯','是,向右转弯']))
                robot.Motor_TurnRight()
                p = GPIO.PWM(8, 3)
                p.start(20)
                time.sleep(0.5)
                p.stop()
                robot.Motor_Stop()
                GPIO.output(8, GPIO.LOW)
                GPIO.output(LED_CTR, GPIO.HIGH)
                
        elif command.find(u"黑") !=-1 and command.find(u"线") !=-1:
                print ("黑线")
                robot.TrackLine()
        
        elif command == "状态":
            os.system('cat deng.txt door.txt tv.txt >all.txt')
            itchat.send_file("/home/pi/dai/command/all.txt",toUserName='filehelper')
        return 

语音聊天

语音聊天国内做的比较好的有图灵机器人、小i机器人,百度的小度也不错,不过还没有什么开放接口,所以目前在使用图灵机器人(采用WEB API 2.0 接口),下面简单介绍一下申请、使用方法等基本流程。

简介

图灵机器人API是在人工智能的核心能力(包括语义理解、智能问答、场景交互、知识管理等)的基础上,为广大开发者、合作伙伴和企业提供的一系列基于云计算和大数据平台的在线服务和开发接口。
开发者可以利用图灵机器人的API创建各种在线服务,灵活定义机器人的属性、编辑机器人的智能问答内容,打造个人专属智能交互机器人。

使用流程

注册申请图灵帐号

登录图灵机器人官方网站http://www.tuling123.com/,点击右上角“注册”按钮进行注册并激活帐号,如下图所示:

注册申请图灵帐号

获取APIKEY

每一个激活用户都可以通过图灵机器人开放平台获取多个APIKEY(当前每个用户可最多获取5个APIKEY),用户可以根据自己的需要获取不同的图灵APIKEY来应用于多种场景,获取成功后就等于拿到了开启图灵服务的钥匙。
登录图灵帐号,进入个人中心,在“我的机器人》机器人详情》接入”页面即可看到每一个机器人的API KEY,如下图所示:


获取APIKEY
编码方式
UTF-8(调用图灵API的各个环节的编码方式均为UTF-8)
接口地址
http://openapi.tuling123.com/openapi/api/v2
请求方式
HTTP POST
请求参数

请求参数格式为 json
请求示例:

{
    "reqType":0,
    "perception": {
        "inputText": {
            "text": "附近的酒店"
        },
        "inputImage": {
            "url": "imageUrl"
        },
        "selfInfo": {
            "location": {
                "city": "北京",
                "province": "北京",
                "street": "信息路"
            }
        }
    },
    "userInfo": {
        "apiKey": "",
        "userId": ""
    }
}

参数说明

参数 类型 是否必须 取值范围 说明
reqType int N - 输入类型:0-文本(默认)、1-图片、2-音频
perception - Y - 输入信息
userInfo - Y - 用户参数

perception

参数 类型 是否必须 取值范围 说明
inputText - N - 文本信息
inputImage - N - 图片信息
inputMedia - N - 音频信息
selfInfo - N - 客户端属性

注意:输入参数必须包含inputText或inputImage或inputMedia!

inputText

参数 类型 是否必须 取值范围 说明
text String Y 1-128字符 直接输入文本

inputImage

参数 类型 是否必须 取值范围 说明
url String Y 图片地址

inputMedia

参数 类型 是否必须 取值范围 说明
url String Y 音频地址

selfInfo

参数 类型 是否必须 取值范围 说明
location - N - 地理位置信息

location

参数 类型 是否必须 取值范围 说明
city String Y - 所在城市
province String N - 省份
street String N - 街道

userInfo

参数 类型 是否必须 取值范围 说明
apiKey String Y 32位 机器人标识
userId String Y 长度小于等于32位 用户唯一标识
groupId String N 长度小于等于64位 群聊唯一标识
userIdName String N 长度小于等于64位 群内用户昵称
输出参数

输出示例:

  {
    "intent": {
        "code": 10005,
        "intentName": "",
        "actionName": "",
        "parameters": {
            "nearby_place": "酒店"
        }
    },
    "results": [
        {
            "groupType": 1,
            "resultType": "url",
            "values": {
                "url": "http://m.elong.com/hotel/0101/nlist/#indate=2016-12-10&outdate=2016-12-11&keywords=%E4%BF%A1%E6%81%AF%E8%B7%AF"
            }
        },
        {
            "groupType": 1,
            "resultType": "text",
            "values": {
                "text": "亲,已帮你找到相关酒店信息"
            }
        }
    ]
}

参数说明

参数 类型 是否必须 取值范围 说明
intent - Y - 请求意图
results - N - 输出结果集

intent

参数 类型 是否包含 取值范围 说明
code int Y - 输出功能code
intentName String N - 意图名称
actionName String N - 意图动作名称
parameters String N - 功能相关参数

results

参数 类型 是否包含 取值范围 说明
resultType String Y 文本(text);连接(url);音频(voice);视频(video);图片(image);图文(news) 输出类型
values - Y - 输出值
groupType int Y - ‘组’编号:0为独立输出,大于0时可能包含同组相关内容 (如:音频与文本为一组时说明内容一致)

核心代码

#coding=utf8
import urllib.request
import json

KEY = 'd4473a5b08da492cad0bc98bb8bc77bb'

def get_response(msg):
    apiUrl = 'http://openapi.tuling123.com/openapi/api/v2'
    data = json.dumps({
                "reqType":0,
                "perception": {
                    "inputText": {
                        "text": msg
                    },
                    "selfInfo": {
                        "location": {
                            "city": "北京",
                            "province": "北京",
                            "street": "中关村南大街"
                        }
                    }
                },
                "userInfo": {
                    "apiKey": KEY,
                    "userId": "123555"
                }
            }).encode('utf-8')
    try:
        r = urllib.request.urlopen(url=apiUrl, data=data)
        t = r.read().decode('utf-8')
        result = json.loads(t)
        return result
    except:
        return
if __name__ == '__main__':
    #get_response('给我一张小狗照片').get('results')('image')
    print (get_response('给我一张小狗照片')['results'][0]['values']['url'].encode('utf-8').decode())

完整代码

所有的代码都上传到了我的GitHub上
Rascar-Wechat — A COOL Raspberry Intelligent car based on the Wechat

系列教程

人工智能-树莓派小车(1)——DuerOS语音唤醒
人工智能-树莓派小车(2)——GPIO接口介绍
人工智能-树莓派小车(3)——GPIO控制小车
人工智能-树莓派小车(4)——通过语音玩转智能小车
人工智能-树莓派小车(5)——用微信控制智能小车

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 159,015评论 4 362
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,262评论 1 292
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,727评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,986评论 0 205
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,363评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,610评论 1 219
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,871评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,582评论 0 198
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,297评论 1 242
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,551评论 2 246
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,053评论 1 260
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,385评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,035评论 3 236
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,079评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,841评论 0 195
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,648评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,550评论 2 270

推荐阅读更多精彩内容