本文作者:zhujue

打造树莓派私人语音助手,年轻人的第一个贾维斯!

zhujue 2024-02-20 12:57:06 50 抢沙发
打造树莓派私人语音助手,年轻人的第一个贾维斯!摘要: ...

目录

[youbanshan]

一、如何打造属于你的私人语音助手之环境搭建

二、唤醒他吧

三、个性化定制



我是谁,谁又是我

Hi, 大家好,我是刘波,人在江湖行走的ID是:IAMLIUBO!受到电子芯吧客平台用户活跃度的感召,为了防止世界被破坏,为了保护世界的和平,于是我决定也要来电子芯吧客平台混个脸熟了(我不会承认我是为了稿费才来的!绝对不会!滑稽.gif)。



一、如何打造属于你的私人语音助手之环境搭建

发布时间: 2019-12-11

语音助手元年(智能音箱元年)

2017年可谓是各大科技巨头争相发布自己生态内智能音箱的元年,前有国外科技巨头亚马逊的Alexa、echo,谷歌的Google Home,苹果的Home Pod等,后有国内巨头阿里巴巴家的天猫精灵系列,京东家的叮当,百度家的小度,小米家的小爱同学等等,真可谓百家争鸣,百花齐放,想必正在读这篇文章的你家中也有个智能音箱吧,作为新一代的家庭智能网关,现在的智能音箱承载了越来越多的功能,比如简单的对话,查快递,询问天气等,还可以跟你家庭中的智能设备联动。
享受过智能音箱带来的便利后,大家有没有对智能音箱是如何工作的有些好奇呢?大家有没有想打造一个属于自己的语音助手呢?
没错,本系列文章就是带大家一步步了解并打造一个属于自己的语音助手。

技术栈

开始打造你的私人助手之前需要掌握以下技能:

  • python开发语言

  • 树莓派开/机

  • git代码管理工具

  • 基本电子电路知识

  • MQTT通讯协议简单了解(后面我们会做跟别的硬件交互)

  • 认识

没错,不需要你有很强的技术就可以很简单的完成本项目,所以完全不用担心,而我也会尽可能详细的给大家一步步的去讲解,保证大家都可以完成这个项目。

硬件准备

没有硬件是不太好开始,所以建议大家配齐以下硬件:
基本:

  • 树莓派(3B/3B+/4都可以)

  • 内存卡(16G)

  • ReSpeaker麦克风阵列

  • 3.5mm迷你小音箱

扩展:

  • 温湿度传感器(DHT11)

  • 土壤湿度传感器

  • 小水泵

  • 树莓派摄像头

  • 0.96寸OLED显示屏

  • 5V小风扇

  • 继电器(x3)

  • NodeMCU(esp8266)

  • (其它在后面文章中补充)

硬件这里分为基本和扩展,基本硬件可以保证你成功运行起属于自己的语音助手,扩展硬件则可以让你有更多的玩法,当然硬件的选择取决于你,我这里只是给出一点建议,关于硬件购买链接这里就不放了,大家自行去某宝搜索购买即可。

更多了解

语音助手基于潘伟洲在Github开源的wukong项目,这是一个非常棒的项目,前身也是基于潘老师写的dingdang-robot,目前已经有1.5K个star,项目主页:wukong
语音唤醒解决方案是采用的snowboy
语音转文字,文字转语音技术采用的是百度大脑语音技术(可选择讯飞或者腾讯阿里)。
自然语言处理采用的是百度UNIT。
聊天对话采用的是图灵机器人(对话库)。

准备工作

硬件:

  • 树莓派

  • 内存卡

  • 读卡器

  • 电源

软件:

如果是初次使用树莓派请准备以上硬件和软件,并将软件安装好,如果是一个树莓派老手,请忽略,直接跳到wukong软件安装环节~

树莓派烧录镜像和开机

本章节只给第一次使用树莓派的新手查看^_^

镜像烧录

打开Win32 Disk Imager软件,来烧写,我们需要先解压前面准备的树莓派镜像文件,解压完成后,在按照如下软件截图进行配置,配置好后点击Write,然后就可以开始写镜像了,此过程一般会持续几分钟,请耐心等待。
打造树莓派私人语音助手,年轻人的第一个贾维斯! 第1张
耐心等待进度条完成。
打造树莓派私人语音助手,年轻人的第一个贾维斯! 第2张
需要注意的是,烧写完成后,可能会弹出以下窗口,让你格式化内存卡,此时一定不要点格式化磁盘!一定不要点格式化磁盘!一定不要点格式化磁盘!
打造树莓派私人语音助手,年轻人的第一个贾维斯! 第3张

设置WiFi名称和密码

上一步完成,我们来给树莓派配置我们的WiFi名称和密码,当然顺便开启SSH服务。
打开文件浏览器,找到一个名称为boot的盘符,打开,并在文件夹内新建一个名称为wpa_supplicant.conf的文件,然后将下面内容保存到文件内,其中ssid=”XXXXXXXXX”的XXXXXXXXX替换成你的家庭路由器WiFi名称,psk=”XXXXXXXXX”的XXXXXXXXX替换成WiFi密码,其余的文件不要修改。

country=CNctrl_interface=DIR=/var/run/wpa_supplicant GROUP=netdevupdate_config=1network={    ssid="XXXXXXXXX"    psk="XXXXXXXXX"    key_mgmt=WPA-PSK    priority=1}

然后我们再新建一个ssh文件,不需要任何内容,也没有任何扩展名,同样也是在boot目录下。
最终效果如下:
打造树莓派私人语音助手,年轻人的第一个贾维斯! 第4张

SSH远程连接

前两步操作完成后,我们就可以将内存卡插到树莓派开机了,树莓配开机后会自动连接我们前面配置的WiFi热点,下一步我们就可以用putty这个软件通过SSH协议连接树莓派了,但是在连接之前我们还需要确认一下我们的树莓派IP地址,我们需要通过路由器的管理后台进行查看,如何登录路由器后台不会的小伙伴可以自行搜索。
比如我这里经查看树莓派的IP地址如下图:
打造树莓派私人语音助手,年轻人的第一个贾维斯! 第5张
PuTTY软件设置:
打造树莓派私人语音助手,年轻人的第一个贾维斯! 第6张
填写好IP后,我们点击Open会弹出一个下面的界面,我们点击是:
打造树莓派私人语音助手,年轻人的第一个贾维斯! 第7张
输入用户和密码登录:
打造树莓派私人语音助手,年轻人的第一个贾维斯! 第8张
出现以下界面,恭喜你登录成功!
打造树莓派私人语音助手,年轻人的第一个贾维斯! 第9张

软件源更改和系统更新

接下来为了更好的在国内使用,我们需要修改一下软件源,如果不修改的话后面安装程序就可能会非常慢,或者经常性安装失败。
我们这里使用清华源,这是树莓派软件包的一个国内源,可以给我们提供更快的访问速度,首先执行以下命令:

sudo nano /etc/apt/sources.list

然后增加下面这两行代码:

deb http://mirrors.tuna.tsinghua.edu.cn/raspbian/raspbian/ buster main non-free contribdeb-src http://mirrors.tuna.tsinghua.edu.cn/raspbian/raspbian/ buster main non-free contrib

打造树莓派私人语音助手,年轻人的第一个贾维斯! 第10张
然后再执行以下代码:

sudo nano /etc/apt/sources.list.d/raspi.list

然后增加下面这行代码:

deb http://mirrors.tuna.tsinghua.edu.cn/raspberrypi/ buster main ui

打造树莓派私人语音助手,年轻人的第一个贾维斯! 第11张
注:nano编辑器的使用方法可以自己搜索以下
最后我们需要分别执行这两句命令更新我们刚刚修改的源和更新已安装的软件:

sudo apt-get updatesudo apt-get upgrade

第二条命令执行时间有点长,请耐心等候一下。

安装wukong依赖库

本片文章我们先安装一下wukong和一些依赖库,下篇文章我们再来编译snowboy。
首先需要将wukong的源码下载下来:

git clone https://github.com/wzpan/wukong-robot.git

安装 sox ,ffmpeg 和 PyAudio:

sudo apt-get install portaudio19-dev python-pyaudio python3-pyaudio sox pulseaudio libsox-fmt-all ffmpegpip3 install pyaudio

安装依赖的库:

cd wukong-robotpip3 install -r requirements.txt

请一行一行的执行上面的命令,拉取源码的时候估计时间会比较久,请耐心等候,如果拉取失败,再次尝试即可。
下篇文章我们再来编译snowboy和安装麦克风阵列驱动。





二、如何打造属于你的私人语音助手之唤醒它吧


第二篇文章的演示视频如下:

【带资料】打造树莓派私人语音助手,年轻人的第一个贾维斯!_哔哩哔哩_bilibili

树莓派 wukong 语音助手


前言

我们在上篇文章中已经将基本环境搭建好了,本片文章让我们开始下一步吧!

准备工作

硬件:

  • 树莓派(结合前文的树莓派)

  • ReSpeaker麦克风阵列

    给个图给大家参考一下吧,这是我使用的硬件。

  • 3.5mm迷你小音箱
    打造树莓派私人语音助手,年轻人的第一个贾维斯! 第12张
    就选择这种很普通的小音箱就可以,虽然效果确实不咋样,但贵在便宜。
    软件:

  • 貌似没有?

软件安装

在上篇文章的最后,我们没有全部完成,所以本节课还需要做一些收尾工作,我们还需要编译我们的语音唤醒方案的一个动态库,还有安装一下麦克风阵列的驱动,因为这两部分相对来说还是比较麻烦的,所以留到了本篇文章来写。

编译snowboy

我们先安装swig,本节操作命令有点多,请仔细执行每一条命令:

#安装依赖库sudo apt-get -y updatesudo apt-get install -y libpcre3 libpcre3-dev#下载并编译安装swig,此步是必须的,不可省略wget http://hahack-1253537070.file.myqcloud.com/misc/swig-3.0.10.tar.gztar xvf swig-3.0.10.tar.gzcd swig-3.0.10./configure --prefix=/usr --without-clisp --without-maximum-compile-warningsmakesudo make installsudo install -v -m755 -d /usr/share/doc/swig-3.0.10sudo cp -v -R Doc/* /usr/share/doc/swig-3.0.10#安装依赖库sudo apt-get install -y libatlas-base-dev

上面有条命令由markdown转码html貌似不成功,请参考下面的:

sudo cp -v -R Doc/@@* /usr/share/doc/swig-3.0.10

如果你觉得一条条的执行比较麻烦,可以新建一个swig_install.sh文件,然后复制上面所有的命令到文件:

sudo nano swig_install.sh

打造树莓派私人语音助手,年轻人的第一个贾维斯! 第13张
然后执行:

./swig_install

然后我们开始编译snowboy的动态库文件,同样的我们执行下面的命令:

wget http://hahack-1253537070.file.myqcloud.com/misc/snowboy.tar.bz2tar -xvjf snowboy.tar.bz2cd snowboy/swig/Python3make

出现跟下图一样的字样,标识编译成功。
打造树莓派私人语音助手,年轻人的第一个贾维斯! 第14张
我们还需要将snowboydetect.so文件复制到wukong-robot目录下的snowboy文件夹。

cp _snowboydetect.so ~/wukong-robot/snowboy/

OK,到这里snowboy动态库我们就编译完成了,不过先不要着急,我们还需要安装麦克风阵列驱动,Let’s go!

安装麦克风阵列驱动

这里我们使用的是两个麦克风的麦克风阵列,虽然不如多麦克风阵列的收音效果好,但是相对来说比较便宜,还是比较不错的,废话少说!

git clone https://github.com/respeaker/seeed-voicecard.git #下载声卡驱动cd seeed-voicecard sudo ./install.sh #安装声卡驱动

我们先从github拉取源码,拉取完成后直接执行安装脚本就可以了,相对是比较简单的,安装完成后我们需要重启,然后断电顺便插上我们的麦克风阵列和小音箱。
打造树莓派私人语音助手,年轻人的第一个贾维斯! 第15张
出现以上界面,我们就可以关机了,然后断掉电源,安装麦克风阵列与音箱,音箱3.5mm插头插座我们先插麦克风阵列上就可以,测试完麦克风阵列后我们再插到树莓派上。

sudo poweroff  #关机

安装好后,我们重新开机测试麦克风阵列是否工作,首先我们查看声卡列表是否有我们的麦克风阵列:

aplay -l

打造树莓派私人语音助手,年轻人的第一个贾维斯! 第16张
然后我们先设置一下音量:
打造树莓派私人语音助手,年轻人的第一个贾维斯! 第17张

然后你可以录音测试一下:

arecord -f cd -Dhw:1 | aplay -Dhw:1 #声音会越来越大,建议保护耳朵,ctrl+c退出

如果能听到自己声音,就没问题了,然后你可以将音箱再插回树莓派上!

运行wukong

接下来让我们正式开始运行起来吧,这里默认唤醒词是孙悟空,不过效果不太好,因为是作者自己训练的,当然你可以可以更换成你想要的唤醒词,这里我们先运行起来:

python3 wukong.py

第一次运行会询问我们是否创建config.yml配置文件,我们输入y就可以了,后面我们很多设置都是从这里面更改,目录是/home/pi/.wukong/config.yml,第一次运行可能会唤醒不了,这里不要着急,我们还需要修改一下配置,我们需要先按ctrl+4停止运行,然后输入以下命令:

sudo nano ~/.wukong/config.yml

找到以下内容:

# snowboy 离线唤醒# https://snowboy.kitt.ai/dashboard# 建议到 https://snowboy.kitt.ai/hotword/32768# 使用相同环境录入你的语音,以提升唤醒成功率和准确率hotword: 'wukong_pi.pmdl'  # 唤醒词模型,如要自定义请放到 $HOME/.wukong 目录中sensitivity: 0.4  # 灵敏度silent_threshold: 15 # 判断为静音的阈值。环境比较吵杂的地方可以适当调大recording_timeout: 5 # 录制的语音最大长度(秒)snowboy_token: your_token # 你的token,用于 train 命令训练语音

将其中hotword的wukong.pmdl修改为wukong_pi.pmdl,然后保存退出就可以运行并唤醒了,唤醒效果不会像我们买的智能音箱一样,提前给大家打个预防针,主要原因还是因为训练样本不够,会面会教大家如何训练和修改自己的唤醒词。
如果修改配置文件及运行,可以参考下面动态图:
打造树莓派私人语音助手,年轻人的第一个贾维斯! 第18张
运行效果演示视频可以到DIY视频版块查看(管理员还在审核中…)。

接下来我们安装一下第三方技能插件库,第三方技能插件库是除作者之外的开发者贡献的技能,我们也是可以直接使用的,后面我们也会将如何开发属于自己的技能,这里我们先安装一下别人写好的技能。

cd ~/.wukonggit clone http://github.com/wzpan/wukong-contrib.git contribpip3 install -r contrib/requirements.txt

请一定要切换到~/.wukong这个目录下安装,因为技能默认都会从这里面加载,那么都有哪些用户技能呢,大家可以从这个链接查看:
用户贡献技能

后台管理界面

我们还可以通过web后台跟语音助手互动,我们可以通过电脑浏览器输入树莓派的IP地址加端口号进行访问:
打造树莓派私人语音助手,年轻人的第一个贾维斯! 第19张
然后我们可以像打字聊天一样进行交互:
打造树莓派私人语音助手,年轻人的第一个贾维斯! 第20张
尽情去体验吧~

OK,本篇文章就到这里,下一篇文章教大家如何训练自己的唤醒词以及个性化修改等等,后面还会教大家如何开发自己的技能!



三、如何打造属于你的私人语音助手之个性化定制

前言

我们在上一篇文中已经成功运行起来了我们的私人语音助手——孙悟空,等等?你是认真的?叫孙悟空?是的,默认唤醒词就是我们童年最美好的记忆,但是我们老孙悟空,孙悟空的喊,有没有觉得自己有点像唐僧呢?哈哈,那么本节课就带大家做一些个性化定制,让它真正属于你的“私人”助手。

准备

硬件:

  • 安装好wukong的树莓派

  • 貌似没其它了

软件:

开始

换掉唤醒词,拒绝做唐僧!

第一步我们先从换掉唤醒词开始,毕竟作为一个合格的程序员,拒绝做唐僧是我们最后的倔强(暗示不脱发!拒绝联想!)。我们在前面的文章中讲过,这里使用的唤醒方案是snowboy,所以我们需要到snowboy官方网站进行唤醒词训练!
戳链接直达:snowboy
这里你需要登录,可以直接使用Github登录,简单方便又快捷!
打造树莓派私人语音助手,年轻人的第一个贾维斯! 第21张
如果你是第一次登录还未训练任何模型,下载前都需要参与训练,如何训练也很简单,每一步也都有指引,训练过的模型可以直接点击下载按钮下载即可,这里我以小白这个唤醒词给大家演示一下!
打造树莓派私人语音助手,年轻人的第一个贾维斯! 第22张
下载好后,我们上传到树莓派下面这个目录即可:
打造树莓派私人语音助手,年轻人的第一个贾维斯! 第23张
接下来我们修改一下配置文件的这一部分,将其中的hotword部分修改为我们刚下载的那个模型,如下:

# snowboy 离线唤醒# https://snowboy.kitt.ai/dashboard# 建议到 https://snowboy.kitt.ai/hotword/32768# 使用相同环境录入你的语音,以提升唤醒成功率和准确率hotword: 'xiaobai.pmdl'  # 唤醒词模型,如要自定义请放到 $HOME/.wukong 目录中sensitivity: 0.4  # 灵敏度silent_threshold: 15 # 判断为静音的阈值。环境比较吵杂的地方可以适当调大recording_timeout: 5 # 录制的语音最大长度(秒)snowboy_token: your_token # 你的token,用于 train 命令训练语音

配置文件目录HOME/.wukong/config.yml
如果唤醒效果不太理想,可以将灵敏度调大一点,比如0.5,不要太大!则误唤醒率会非常高,修改完成后可以运行测试一下:
打造树莓派私人语音助手,年轻人的第一个贾维斯! 第24张

主人信息修改

细心的同学可能发现了,每次开机都是喊你师父,然后上面我们询问天气的时候,可能位置信息也不是你所处的位置,不过这些都是可以修改的,可能很多同学已经发现了,也是在我们的那个配置文件中:

robot_name_cn: '小白first_name: '大哥last_name: ''timezone: HKTlocation: '济南

大家可以根据自己的喜好进行修改,修改完成后再次运行就会使用新的配置了。
打造树莓派私人语音助手,年轻人的第一个贾维斯! 第25张

男声不好听?

默认发音人为男生,可能很多”宅男”,不太喜欢听,想要改成女声,那么能改吗?当然可以更改,同样的配置文件中如下部分:

# 百度语音服务# http://yuyin.baidu.com/baidu_yuyin:    appid: '9670645'  # 建议使用自己的百度语音账户 APPID    api_key: 'qg4haN8b2bGvFtCbBGqhrmZy'    secret_key: '585d4eccb50d306c401d7df138bb02e7'    dev_pid: 1936   # 1936: 普通话远场,1536:普通话(支持简单的英文识别),80001:ASR极速版(请使用自己的百度语音账户再使用)    per: 1  # 发音人选择 0:女生;1:男生;3:度逍遥;4:度丫丫    lan: 'zh'

我们只需要将per: 1 中的数字改成0就可以了,当然还提供了其它两种发音人,大家可以自行尝试。
当然上面的修改是基于你选择的是百度文字转语音服务,如果选用的其它的,需要针对性再修改,我们可以从配置文件中发现,一共提供了下面几家的语音服务,默认的语音识别和文字转语音都是使用的百度的API。

# 语音合成服务配置# 可选值:# han-tts       - HanTTS# baidu-tts     - 百度语音合成(推荐)# xunfei-tts    - 讯飞语音合成# ali-tts       - 阿里语音合成(推荐)# tencent-tts   - 腾讯云语音合成(推荐)tts_engine: baidu-tts

大家如果想换其它家的,只需要将tts_engine后面的值修改成对应的即可。

邮件提醒

没错,还可以使用wukong查询你的邮箱是否有邮件:

# 邮箱# 如果使用网易邮箱,还需设置允许第三方客户端收发邮件email:    enable: true    address: '你的邮箱地址'    password: '你的邮箱密码'  # 如果是网易邮箱,须填写应用授权密码而不是登录密码!    smtp_server: 'smtp.163.com'    smtp_port: '25'  # 这里填写非SSL协议端口号    imap_server: 'imap.163.com'    imap_port: '143'  # 这里填写非SSL协议端口号        read_email_title: true  # 当有邮件时,是否朗读邮件标题

QQ邮箱也建议你使用授权码登录!然后QQ邮箱的收件服务器是:imap.qq.com,发件服务器是:smtp.qq.com

管理后台密码修改

大家还记得上篇文章中的管理后台吗?当时是默认密码,这里教大家修改一下密码:

# 后台管理端server:    enable: true    host: '0.0.0.0'  # ip 地址    port: '5000'     # 端口号    username: 'admin'  # 用户名    # cookie 的 secret ,用于对 cookie 的内容进行加密及防止篡改    # 建议使用 os.urandom(24) 生成一串随机字符串    # 强烈建议修改!!!    cookie_secret: '456134b90bf73510cc5eb2ab8b7948e7400f8c6781d3fb86'    # 密码的 md5,可以用 python3 wukong.py md5 "密码" 获得    # 初始密码为 wukong@2019    # 强烈建议修改!!!    # 我这里修改成了 XXXXXXXX    validate: '1c6e488449e3741a999388f7bd7d07ae'

用户名是明文,大家可以自由修改,建议大家不要修改成汉字哦!
如何修改可以看下面的动态图:
打造树莓派私人语音助手,年轻人的第一个贾维斯! 第26张
贴一下python代码给大家:

import osimport binasciiprint(binascii.hexlify(os.urandom(24)))

登录测试,可以看到我使用的是admin这个用户名登录的,然后密码是使用的 XXXXXXXX,能够登录成功就说明我们已经修改成功了!
打造树莓派私人语音助手,年轻人的第一个贾维斯! 第27张

OK,本篇文章就到这里,下篇文章教大家如何开发技能,以及技能是如何开发的,纳尼?你是认真的?简而言之就是开发一个你自己的技能!




四、如何打造属于你的私人语音助手之植物识别


前言

距离上一篇文章,已经过去一段时间了,不知道大家有没有成功跑起来呢?最近比较忙,也没能持续更新,不过今晚忙里偷闲,给家更新一篇!本篇文章教大家如何开发一个技能——植物识别!没错就是通过摄像头识别植物!不过这里我们是调用的百度接口,没错百度AI接口,使用了很长时间了,感觉准确率还是可以的,貌似百度在国内的几家大厂中,图像识别做的还是非常不错的。

准备

硬件

  • 摄像头(个人推荐使用CSI接口的)

软件

百度AI应用创建

相信注册账号,大家肯定都比较熟练了,这里也就不给大家一步步的演示了,大家打开下面的官网链接,相信一看就知道去哪里注册了:
百度AI开发平台
这里我给大家演示一下如何注册一个图像识别的应用,其实也非常简单,一共四大步,我们就可以完成一个应用的创建:

  • 先从控制台找到图像识别应用
    打造树莓派私人语音助手,年轻人的第一个贾维斯! 第28张

  • 然后点击创建应用按钮:
    打造树莓派私人语音助手,年轻人的第一个贾维斯! 第29张

  • 然后按照下面的格式填好你的应用属性,不一定跟我的一样,然后最后点击创建应用就可以了:
    打造树莓派私人语音助手,年轻人的第一个贾维斯! 第30张

  • 最后回到应用列表,可以看到有AppID、API Key和Secret Key,一会我们需要用到这几个参数,大家知道在这里找就可以:
    打造树莓派私人语音助手,年轻人的第一个贾维斯! 第31张
    到这里我们的百度AI图像应用就创建好了,其实就是为了得到上面那几个密钥。

依赖库安装

所谓的依赖库其实就是百度给我们写好的SDK,这里我们选择python SDK来进行开发,因为我们的语音助手的代码也是用python来写的,安装方法也很简单,大家只需要执行下面的一条命令即可:

sudo pip install baidu-aip

相信大家多多少少对python应该都有一部分了解,我们安装好依赖库后,基本就都准备好了,baidu-aip怎么用,可以去看一下百度的文档:文档链接,当然你还需要将你的硬件连接起来,就是需要把你的摄像头使用FPC软排线跟树莓派连接起来,相信聪明伶俐的你肯定会的!

如何开发一个技能?

其实我们自己去开发技能还是非常简单的,因为很多麻烦的地方作者都已经帮我们处理好了,当然大家也可以看一下文档:技能开发,不过这里还是简单给大家介绍一下。

准备工作

创建一个文件夹,用来存放我们的技能代码:

sudo mkdir -p ~/.wukong/custom

没错就是在在.wukong这个目录下创建一个custom文件夹,名称是固定的,这里的路径相信你的跟我的应该也一样,这是官方文档中固定的,大家按照这个格式去写好了。

不知道大家还记得那个配置文件吗?就是在个性化定制的那篇文章中我们修改了很多参数的那个配置文件,这里我们增加一些内容到里面:

nano ~/.wukong/config.yml

在文件的最后增加以下内容:

#植物识别#使用百度AI接口#作者: IAMLIUBOplantDetect:    enable: true    appid: 'XXXXXXXXXXX'    api_key: 'XXXXXXXXXXX'    secret_key: 'XXXXXXXXXXX'    type: 1                 # 摄像头类型 0:usb_camera,1:树莓派 5MP 摄像头,2$    dest_path: "/home/pi/Pictures/" # 保存目录    quality: 5              # 成像质量(0~100),不支持 imagesnap    vertical_flip: true     # 竖直翻转,不支持 imagesnap    horizontal_flip: true  # 水平翻转,不支持 imagesnap    count_down: 3           # 倒计时(秒),仅当开启倒计时时有效

不过这里你需要注意了,请将上面的 XXXXXXXXXXX 替换成我们在上面创建百度AI应用得到的appid、api_key和secret_key,不然后面运行会出错的!一定要记得修改!
到这里准备工作基本就完成了,如果你是第一次使用摄像头的话,记得先运行:

sudo raspi-config

然后在Interfacing Option里面找到Camera并使能,不然后面还是会报错的!

颤抖吧!少年!

哈哈,开玩笑,准备工作都准备好了,那我们就开始运行代码吧,不过我们需要先写好程序:

nano ~/.wukong/custom/CameraPlantDetect.py

然后复制下面的代码并保存:

# -*- coding: utf-8-*-# Camera plant detect# author: IAMLIUBO# github: https://github.com/imliubo# website: https://blogs.oopswow.comimport osimport subprocessimport timefrom robot import config, constants, loggingfrom robot.sdk.AbstractPlugin import AbstractPluginfrom aip import AipImageClassifylogger = logging.getLogger(__name__)options = {}options["baike_num"] = 1def get_file_content(filePath):    with open(filePath, 'rb') as fp:        return fp.read()class Plugin(AbstractPlugin):    SLUG = "plantDetect"    def handle(self, text, parsed):        APP_ID = config.get('/plantDetect/appid')        API_KEY = config.get('/plantDetect/api_key')        SECRET_KEY = config.get('/plantDetect/secret_key')        client = AipImageClassify(APP_ID, API_KEY, SECRET_KEY)        quality = config.get('/plantDetect/quality', 100)        count_down = config.get('/plantDetect/count_down', 3)        dest_path = config.get('/plantDetect/dest_path', os.path.expanduser('~/Pictures'))        device = config.get('/plantDetect/device', '/dev/video0')        vertical_flip = config.get('/plantDetect/verical_flip', False)        horizontal_flip = config.get('/plantDetect/horizontal_flip', False)        camera_type = config.get('/plantDetect/type', 1)        if config.has('/plantDetect/usb_camera') and config.get('/plantDetect/usb_camera'):            camera_type = 0        try:            if not os.path.exists(dest_path):                os.makedirs(dest_path)        except Exception:            self.say(u"抱歉,照片目录创建失败", cache=True)            return        dest_file = os.path.join(dest_path, "%s.jpg" % time.time())        if camera_type == 0:            # usb camera            logger.info('usb camera')            command = ['fswebcam', '--no-banner', '-r', '1024x765', '-q', '-d', device]            if vertical_flip:                command.extend(['-s', 'v'])            if horizontal_flip:                command.extend(['-s', 'h'])            command.append(dest_file)        elif camera_type == 1:            # Raspberry Pi 5MP            logger.info('Raspberry Pi 5MP camera')            command = ['raspistill', '-o', dest_file, '-q', str(quality)]            if count_down > 0 :                command.extend(['-t', str(count_down*1000)])            if vertical_flip:                command.append('-vf')            if horizontal_flip:                command.append('-hf')        else:            # notebook camera            logger.info('notebook camera')            command = ['imagesnap', dest_file]            if count_down > 0 :                command.extend(['-w', str(count_down)])        if count_down > 0:            self.say(u"收到,%d秒后启动拍照" % (count_down), cache=True)            if camera_type == 0:                time.sleep(count_down)        try:            subprocess.run(command, shell=False, check=True)                            self.play(constants.getData('camera.wav'))            image = get_file_content(dest_file)            result = client.plantDetect(image, options)            plant_name = result['result'][0]['name']            try:                baike_info = result['result'][0]['baike_info']['description']                buffer = u"主人,识别到的植物是%s,百度百科描述是%s"%(plant_name, baike_info)                self.say(buffer, cache=False)            except KeyError:                buffer = u"主人,识别到的植物是%s,暂无百度百科描述"%(plant_name)                self.say(buffer, cache=False)        except subprocess.CalledProcessError as e:            logger.error(e)            self.say(u"拍照失败,请检查相机是否连接正确", cache=True)      def isValid(self, text, parsed):        return any(word in text for word in [u"植物识别",u"植物"])

大家先不用了解代码是怎么写的,当然我这里写的可能也不够好,因为我平常主要做嵌入式开发,python只是业余爱好,保存好后我们就可以直接运行wukong了。

为了方便大家测试,这里给大家贴张图片,大家可以将摄像头对准下面的图片,然后唤醒悟空,并对它说 “植物识别” 或者 “植物” 都可以:
打造树莓派私人语音助手,年轻人的第一个贾维斯! 第32张

不出意外的话,应该可以准确识别出牡丹花,并且播放牡丹花的百度百科!
OK,本篇文章就到这里,大家可以先去测试,有问题可以在评论里提出,后面我会录制一个测试视频给大家!



五、如何打造属于你的私人语音助手之MQTT开发


前言

大家还记得我们前面的树莓派私人语音助手的几篇文章吗?之前年底比较忙,没能连续更新,然后又在家度过了一个漫长的假期,最近准备抽时间重新开始更新一下,本篇文章是我们将我们的私人语音助手打造成真正小助手的第一步,我们将会在树莓派上安装一个MQTT server,用来承载我们在局域网内设备间的交互,后面我们就可以通过语音利用MQTT来控制我们的其它设备了,我想你应该知道我在讲什么~

准备

在本篇文章中,你需要准备以下内容:
硬件

  • 树莓派(已经搭建好wukong的pi)

  • ESP8266(建议NodeMCU)
    软件

  • MQTT.fx(测试用,建议先下载安装,并学一下怎么用)

这就是学习本篇文章,你需要准备的所有的东西了,当然一个可以正常上网的条件也是必不可少的。

安装MQTT server

可能有同学对MQTT不是很熟悉,建议大家可以先去google一下,或者可以看一下我写的这两篇篇文章,以便对MQTT有大致的认识,由于内容比较多,这里就不全贴过来了,大家可以点击下面链接去查看:
物联网标配MQTT初相识
物联网标配MQTT服务端软件

Mosquitto简单了解

这是一款Eclipse 团队开发的超轻量级的软件,安装大小仅有几百KB,当然如此轻量级功能上是没有EMQX那么强大了,仅支持MQTT V3协议,不过做测试还是比较好用的,不用在自己的机器上起一个像EMQX那么大的服务,官网也没做太多的介绍,只有一个简短的介绍:

Eclipse Mosquitto is an open source (EPL/EDL licensed) message broker that implements the MQTT protocol versions 5.0, 3.1.1 and 3.1. Mosquitto is lightweight and is suitable for use on all devices from low power single board computers to full servers.
The MQTT protocol provides a lightweight method of carrying out messaging using a publish/subscribe model. This makes it suitable for Internet of Things messaging such as with low power sensors or mobile devices such as phones, embedded computers or microcontrollers.
The Mosquitto project also provides a C library for implementing MQTT clients, and the very popular mosquitto_pub and mosquitto_sub command line MQTT clients.

当然这不是唯一的选择,我们这里选择Mosquitto主要原因还是因为Mosquitto足够小巧,毕竟我们是在树莓派上跑着这个server的,所以像EMQTT这种比较专业的就有点吃力了。

安装Mosquitto

安装也相对简单,大家依次执行以下命令就可以了。

wget http://repo.mosquitto.org/debian/mosquitto-repo.gpg.keysudo apt-key add mosquitto-repo.gpg.keysudo wget http://repo.mosquitto.org/debian/mosquitto-buster.listsudo apt-get updatesudo apt-get install mosquitto

安装完成后,我们先来检查一下,是否正常运行,输入以下命令,并看到跟下面的图片一样,说明你已经成功安装并运行起来了:

service mosquitto status

打造树莓派私人语音助手,年轻人的第一个贾维斯! 第33张

安装mosquitto-clients

上面我们已经安装好了服务端,这里我们再顺便安装一下客户端,安装好后我们就可以测试一下能不能正常使用了,安装也很简单,直接输入下面命令就可以:

sudo apt-get install mosquitto-clients

打造树莓派私人语音助手,年轻人的第一个贾维斯! 第34张
输入Y就可以完成安装了,下面我们来进行测试。

测试

这里我们通过下面三种方式去测试,以帮助大家有更好的认识:

  • mosquitto-clients

  • MQTT.fx

  • ESP8266

第一种方式,我们是在树莓派上测试的,可以验证是否可以正常工作,然后第二种方式我们在Windows上通过MQTT软件进行测试,这里可以验证局域网通信是否正常,然后第三种方式是通过ESP8266去测试,可以验证我们后面就可以愉快的跟硬件交互了。

mosquitto-clients

这个测试相对简单,不过大家需要使用putty类似的软件再打开一个窗口,然后我们在窗口1窗口2分别输入以下命令:
窗口1

mosquitto_sub -t "/icxbk/IAMLIUBO" -v

窗口2

mosquitto_pub -t "/icxbk/IAMLIUBO" -m "Hello,icxbk!"

如果你看到跟下图一样的效果,就说明没问题了!
打造树莓派私人语音助手,年轻人的第一个贾维斯! 第35张
这里给大家简单说一下这几个参数的含义:

  • -t 这表示主题,后面跟着的参数就是我们发布消息的主题,如果你不太明白什么是主题,可以看上面我贴出的两篇文章链接的第一篇。

  • -v 表示收到的消息内容是可见的,也就是通过控制台打印出来

  • -m 表示实际发送的消息内容,这里的消息主题要与我们通过mosquitto_sub订阅的主题保持一致

MQTT.fx

我们再在Windows上通过MQTT.fx软件测试一下,首先你需要配置一下MQTT broken,依次点击Extras->Edit Connection Profiles->右下角加号,然后配置一下IP,如下图:
打造树莓派私人语音助手,年轻人的第一个贾维斯! 第36张
然后我们使用Pulish发送一条消息,如下图,但是不要忘记先点击Connect哦~
打造树莓派私人语音助手,年轻人的第一个贾维斯! 第37张
如果你设置没问题的画,就可以在putty窗口1中看到我们发的消息了,大家如果有不会使用MQTT.fx软件的,建议大家可以先去学习一下。

ESP8266

使用ESP8266可能对部分没有接触过的同学显得稍微有点麻烦,这里我们使用Arduino来开发ESP8266,大家如果还没搭建好开发环境的话,可以参考我的下一篇文章,因为后面我们还会多次用到ESP8266,所以我会教大家如何用Arduino IDE来开发ESP8266,建议大家可以先去看一下文章,再回来这里继续。
下面直接贴上代码,代码也很简单,我们这里使用的是EspMQTTClient这个库,大家可以通过库管理器来进行安装。

#include "EspMQTTClient.h"void onConnectionEstablished();EspMQTTClient client(  "XXXXXXXXXX",                 // Wifi 名称  "XXXXXXXXXX",                 // Wifi 密码  onConnectionEstablished,      // MQTT connection established callback  "XXX.XXX.XXX.XXX"             // 树莓派IP);void setup(){  Serial.begin(115200);}void onConnectionEstablished(){  // Subscribe to "mytopic/test" and display received message to Serial  client.subscribe("/icxbk/IAMLIUBO", [](const String & payload) {    Serial.println(payload);  });  // Publish a message to "mytopic/test"  client.publish("/icxbk/IAMLIUBO", "This is a message form ESP8266!");}void loop(){  client.loop();}

大家需要将代码中这一部分的内容替换为你自己的:

EspMQTTClient client(  "XXXXXXXXXX",                 // Wifi 名称  "XXXXXXXXXX",                 // Wifi 密码  onConnectionEstablished,      // MQTT connection established callback  "XXX.XXX.XXX.XXX"             // 树莓派IP);

编辑好后,就可以编译下载了,下载成功后你会在putty窗口1中看到我们发的消息了,如下图:
打造树莓派私人语音助手,年轻人的第一个贾维斯! 第38张

后记

本篇文章是我们后面继续开发我们的私人语音助手的基础,请大家一定要仔细做,可能会有部分代码由markdown格式渲染成html会出现乱码,如果有不能正常执行的代码可以在评论区留言。


六、如何打造属于你的私人语音助手之控制LED灯(NodeMCU)


前言

我们在上篇文章中,已经在树莓派上搭建好了MQTT server,既然都搭建好了,岂有不用的道理?那么本篇文章就教大家语音控制LED灯!带你解锁更多技能!

准备

在本篇文章中,你需要准备以下内容:
硬件

  • 树莓派(已经搭建好wukong的pi,初学者请从前面几篇文章开始)

  • ESP8266(建议NodeMCU,芯吧客商城有售)

  • LED灯(直插的就可以)

软件

  • Arduino IDE

这就是本篇文章需要准备的硬件跟软件,相信大多数Geek应该都有吧,那么废话说少,接下来开始!本次文章代码分为树莓派和NodeMCU两部分,我们先来看树莓派上的设置。

树莓派

config.yml配置修改

本篇文章我们使用的是chenzhuo贡献的ControMqtt技能,相关介绍,大家可以从这个网址进行参考:
wukong-ControMqtt-chenzhuo
由于这个技能是之前dingdang,也就是wukong的前身的一个项目,有两处需要简单修改一下,这里我们先修改一下config.yml配置文件,增加关于MQTT的几个配置。
我们在config.yml文件的最后增加以下内容:

# 使用mqtt与其他设备连接,作为PublishermqttPub:    host: 'XXX.XXX.XXX.XXX' #替换为你树莓派IP,或者其它MQTT server的IP    port: '1883'            #MQTT Server默认的端口号    topic_s: '/wukong/mqtt' #接收设备反馈信息的主题

大家增加上面的内容就可以了。

ControMqtt.py 代码修改

大家可以直接copy下面的代码,然后覆盖掉原来的就可以了,下面的代码我已经PR到wukong-contrib仓库,正在等在wzpan大佬的审核,我已经测试过,没有问题。

# -*- coding: utf-8 #author: chenzhuo#Raspberry Pi or other platform can connect to the mqtt client,publisher and subscriber can access to bidirectional communication by switching their identities.#Example:you can get temperature of the enviroment collected by Arduino using Raspberry Pi when Raspberry Pi and Arduino communicate with each other.#The actions' file must be /home/pi/.wukong/action.json#Fix: Hcreak 2019.10#Fix: imliubo 2020.04 NodeMCU code reference: https://wukong.hahack.com/#/contrib?id=controlmqttimport paho.mqtt.client as mqttimport paho.mqtt.publish as publishimport timeimport jsonimport osfrom robot import config, loggingfrom robot.sdk.AbstractPlugin import AbstractPluginlogger = logging.getLogger(__name__)class Plugin(AbstractPlugin):    SLUG = "mqttPub"    def search_word(self, text):        home_dir = os.path.expandvars('$HOME')        location = home_dir + '/.wukong/action.json'        if os.path.exists(location):            f = open(location).read()            try:                fjson = json.loads(f)                for key in fjson.keys():                    value = fjson[key]                    if isinstance(value,list):   # 向上兼容                        for word in value:                            if word in text:                                return key,word                    if isinstance(value,dict):                        for word in value.keys():                            if word in text:                                return key,value[word]            except Exception as e:                logger.error(e)                self.say("抱歉出了问题", cache=True)                return        else:                return    def handle(self, text, parsed):        profile = config.get()        #get config        if ( self.SLUG not in profile ) or ( 'host' not in profile[self.SLUG] ) or ( 'topic_s' not in profile[self.SLUG] ):            self.say("主人,配置有误", cache=True)            return        host = profile[self.SLUG]['host']        port = 1883        if ( 'port' in profile[self.SLUG] ):            port = int(profile[self.SLUG]['port'])        topic_s = profile[self.SLUG]['topic_s']        # text = text.split(",")[0]   #百度语音识别返回的数据中有个中文,        topic_p,payload = self.search_word(text)        try:            # self.say("已经接收到指令", cache=True)            mqtt_contro(host,port,topic_s,topic_p,payload,self.con)        except Exception as e:            logger.error(e)            self.say("抱歉出了问题", cache=True)            return    def isValid(self, text, parsed):        if self.search_word(text) == None:            return False        else:            return Trueclass mqtt_contro(object):    def __init__(self,host,port,topic_s,topic_p,message,mic):        self._logger = logging.getLogger(__name__)        self.host = host        self.port = port        self.topic_s = topic_s        self.topic_p = topic_p        self.message = message        self.mic = mic        self.mqttc = mqtt.Client()        self.mqttc.on_message = self.on_message        self.mqttc.on_connect = self.on_connect        #mqttc.on_publish = on_publish        #mqttc.on_subscribe = on_subscribe        #mqttc.on_log = on_log        if self.host and self.topic_p:            publish.single(self.topic_p, payload=self.message, hostname=self.host,port=self.port)            if self.port and self.topic_s and self.host:                self.mqttc.connect(self.host, self.port, 5)                self.mqttc.subscribe(topic_s, 0)            #while True:            #    self.mqttc.loop(timeout=5)            self.mqttc.loop_start()    def on_connect(self,mqttc, obj, flags, rc):        if rc == 0:            pass        else:            self._logger.critical("error connect")    def on_message(self,mqttc, obj, msg):        if msg.payload:            self.mqttc.loop_stop()            self.mqttc.disconnect()            self.mic.say(str(msg.payload.decode("utf-8")))        else:            time.sleep(5)            self.mqttc.loop_stop()            self.mqttc.disconnect()            self.mic.say("连接超时", cache=True)    def on_publish(self,mqttc, obj, mid):        self._logger.debug("mid: " + str(mid))    def on_subscribe(self,mqttc, obj, mid, granted_qos):        self._logger.debug("Subscribed: " + str(mid) + " " + str(granted_qos))    def on_log(self,mqttc, obj, level, string):        self._logger.debug(string)

增加 action.json 文件

这个文件是非常重要的,因为这里面的配置是用来命中技能和跟我们的下位机进行交互的,不过非常简单,我这里只加了一设备的配置,你如果还有别的设备,可以多加一点。

{    "开发板一": ["开灯","关灯"]}

这里来给大家稍微解释一下,方便大家任意的添加其它设备。
其中开发板一这个名字可以随便修改,其实这是一个MQTT主题,也就是我们下位机(NodeMCU)订阅的主题,你可以修改为其它的,然后开灯关灯,是下发的命令,也是我们命中技能的关键词,当你唤醒wukong时,如果说出了开灯或者关灯,就会命中当前技能,然后向开发板一这个主题发送命令,我们的下位机收到后,通过比对命令,就可以触发响应的操作了。

这就是我们需要在树莓派上需要进行的所有操作,下面我们再来看看NodeMCU的代码。

NodeMCU

代码

大家还记得我们在如何打造属于你的私人语音助手之MQTT开发这篇文章中的代码吗?没错,本节的代码就是在那篇文章的基础上简单修改了下,直接上代码:

/@@* wukong-robot control the NodeMCU by MQTT   Compile with Arduino IDE   Author: IAMLIUBO   Github: github.com/imliubo*/#include "EspMQTTClient.h"#define LED_PIN     D0#define BLINK_PIN   D4void onConnectionEstablished();EspMQTTClient client(  "xxxxxxxxx",                 // Wifi ssid  "xxxxxxxxx",                 // Wifi password  onConnectionEstablished,     // MQTT connection established callback  "192.168.1.57",              // MQTT broker ip  1883,                       // MQTT broker port  "",                         // MQTT username  "",                         // MQTT password  "nodeMCU"                   // Client name  );long lastTime = 0;uint8_t pin_status = 0;void LED_Control_Callback(const String & payload) {  const char* p = payload.c_str();  //  Serial.println(p);  if (strstr(p, "开灯")) {              //命令会在MQTT消息中传过来,我们通过利用strtr()函数,就可以执行相应的操作了。    digitalWrite(LED_PIN, LOW);    client.publish("/wukong/mqtt", "主人,灯已打开!");// "/wukong/mqtt" 是在config.yml中定义的 topic_s 字段,用来回复wukong_robot的自定义消息,也就是执行完命令后的语音,  }  if (strstr(p, "关灯")) {    digitalWrite(LED_PIN, HIGH);    client.publish("/wukong/mqtt", "主人,灯已关闭!");  }}void onConnectionEstablished(){  client.subscribe("开发板一", LED_Control_Callback);// "开发板一" 是在action.json文件中定义的,用来接收wukong-robot下发的命令。}void setup(){  Serial.begin(115200);  pinMode(BLINK_PIN, OUTPUT);  pinMode(LED_PIN, OUTPUT);  digitalWrite(LED_PIN, HIGH);}void loop(){  client.loop();  long now = millis();  if (now - lastTime > 1000) {    lastTime = now;    digitalWrite(BLINK_PIN, !pin_status);    pin_status = !pin_status;  }}

大家如果没有使用过Arduino开发NodeMCU(ESP8266),可以参考我的这篇文章使用Arduino来开发ESP8266先搭建好环境,大家直接将上面的代码下载到NodeMCU就可以了。

运行效果

私人语音助手控制LED演示



[/youbanshan]
文章投稿或转载声明

来源:IAMLIUBO版权归原作者所有,转载请保留出处。本站文章发布于 2024-02-20 12:57:06
温馨提示:文章内容系作者个人观点,不代表天云博客对其观点赞同或支持。

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

微信扫一扫打赏

阅读
分享

发表评论

快捷回复:

评论列表 (暂无评论,50人围观)参与讨论

还没有评论,来说两句吧...