Python轻应用实现语音播报

前言

近年来,随着移动支付的飞速发展,各种线下消费场所都提供了扫码付款的能力。日常生活中,我们常见的有小超市,便利店,农贸市场等。 商家只需要展示自己的收款码,就能收到消费者的付款渠道和金额了。由于商家不可能时刻看着自己的手机去核对首款金额,因此衍生了一个新的产品:播报音箱。 所有的收款信息都可以实时的通过语音播报出来,让商家可以免去收银的烦恼,安心做生意。

本文将要介绍的是如何使用Python轻应用和HaaS100打造一个播报音响产品。

设备端如何使用千里传音?

本方案中,播报设备指的是阿里云的物联网硬件设备HaaS100,App的使用的是在线调试工具或者PC端的Python 应用。具体的交互流程如下:

千里传音代码方案

以上代码逻辑,均在Python轻应用中实现,具体细节轻参考物品清单章节中的Python轻应用固件软件部分。

物品清单

硬件

  1. HaaS100 开发板一块

  2. 电源一个

  3. micro usb 一个

  4. sdcard 一个

  5. 有源喇叭一个 购买链接

  6. 杜邦线一根

注意事项:

  1. HaaS100支持外接微型SD卡(Micro SD),最大支持64GB数据的存储,SD卡槽位于开发板背,可以外接微型SD存储卡

  2. sdcard 格式支持: FAT16/FAT32,本案例中暂时不支持exFAT 格式

  3. 喇叭的链接方法如下:

    喇叭

软件

千里传音产品和设备创建

● 创建项目

登录阿里云官网,选择产品阿里云IoT平台->企业物联网平台->控制台->增值服务->IoT云端一体服务,进入千里传音服务后台

创建项目

在项目创建过程中,需要输入项目名称,并对项目进行简单描述,以便后期维护。

项目描述

在完成项目创建后,系统将帮助用户创建一个与项目名相同的产品,以便后续加入设备。同时,如果用户希望为设备增加千里传音以外的能力,也可以直接到物联网平台的设备管理界面中,为设备添加物模型能力。 在项目列表中,点击需要配置的项目,可以对项目内容进行配置管理。

项目配置

在项目配置界面,有两个选项,分别是服务配置和设备管理,其中服务配置是用来配置千里传音服务的的,主要是语料管理,设备配置是用来管理项目中设备列表的。

● 生成语料

如下图所示,在项目配置中,选中服务配置->管理服务,

服务配置

进去千里传音服务配置界面以后,选中语料配置中的新增语料

新增语料

新增自定义语料界面如下:

语料自定义

其中语料标识和语料内容非常重要,语料标识必须是项目级别唯一,它是作为语料组合调用时候的唯一标签,同时也作为设备端保存语料的文件名。语料内容指的就是我们要播报的文本. 除此之外,我们还可以自定义语料的场景,包括方言场景,童声场景,客服场景以及通用场景;自定义语料的播放速度;自定义语料的播报音量等。

● 创建设备

在完成语料构建和管理后,需要在项目中创建设备,以便最终用户的播报应用可以将命令发送到设备端,完成整个播报链路。点击“设备管理”标签,将进入设备管理界面。

设备管理1

设备创建可以有单个创建和批量创建两种方式。 点击“创建设备”会打开创建单个设备弹窗,并要求用户输入设备相关信息。

设备管理2

DeviceName:英文字符组成的设备名称,设备名称在项目中不可重复。 备注名称:为了便于用户区分设备,给设备赋予的别名。 点击“批量添加”会打开批量创建设备弹窗

批量添加

添加方式

○ 自动生成:指系统将为用户自动生成DeviceName。

○ 批量上传:需要用户通过.csv文件上传自定义的DeviceName。

设备数量

需要批量添加的设备个数。

在创建完成设备以后,设备管理界面,可以显示设备列表,点击设备对应的鉴权信息,可以查看设备的三元组信息

鉴权信息

语料推送 在创建完成设备以后,我们就可以回到语料配置界面,将新增的语料推送到相应的设备上面进行测试了。 如下图所示,点击需要推送的语料,操作栏中的推送到设备按钮(下图中我们推送的语料id是 yuan)

推送到设备

进入语料推送界面,如下图所示,默认支持单个设备推送,分组推送和全部设备推送。

推送列表

单个设备和分组模式,需要选择自己的设备名或者分组名,选中以后点击确定即可完成推送。 HaaS100 Python轻应用固件 可以通过HaaS100 3.3 开源代码编译或者Python轻应用官方固件直接下载(2021.5月份以后),相关下载方法都在Python轻应用快速上手中有详细介绍: Python轻应用快速上手串口工具

MacOS 电脑推荐使用picocom, windows 电脑推荐使用putty, 务必保证设置串口波特率为 1500000


千里传音设备端Python轻应用代码

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
#!/usr/bin/env python
# -*- encoding: utf-8 -*-
'''
@File       :    haas_speech.py
@Description:    file description
@Date       :    2021/04/19 13:56:50
@Author     :    guoliang.wgl
@version    :    1.0
'''
import iot
import utime as time
import http
import ujson as json
import netmgr as nm
from speech_utils import *

# wifi 状态标志位
wifi_connected = False

# wifi热点信息
ssid = 'xxxx'
pwd = 'xxxx'

# 语音播放相关的音频资源文件定义
resDir = "/sdcard/resource/"
tonepathConnected = "fs:/sdcard/resource/connected.wav"
tonepathPowerOn = "fs:/sdcard/resource/poweron.wav"

# 物联网平台相关的key和serect定义
productKey = "xxxx"
deviceName  =    "xxxx"
deviceSecret  =   "xxxx"

on_request = False
on_play = False

def on_wifi_connected(status):
   global wifi_connected
   wifi_connected = True

# 连接wifi网络
def connect_wifi(ssid,pwd):
   global wifi_connected,on_wifi_connected
   nm.init()
   wifi_connected = nm.getStatus()

   if  not wifi_connected:
      nm.register_call_back(1,on_wifi_connected)
      nm.connect(ssid,pwd)

   while True :
      if wifi_connected:
         break
      else:
         print('Waiting for wifi connected')
         time.sleep(1)

   if nm.getStatus():
      print('DeviceIP:' + nm.getInfo()['IP'])
   else:
      print('DeviceIP:get failed')

   print("ConnectWifi finished")

# 物联网平台连接成功的回调函数
def on_connect():
   global player, tonepathConnected
   print('linkkit is connected ')
   play(tonepathConnected)

def on_service(data):
   global on_request, on_play
   print('****** on service ********')
   serviceid = data['id']
   data = json.loads(data['param'])
   if serviceid == "SpeechPost":
         on_request = data
   elif serviceid == "SpeechBroadcast":
         on_play = data
   else:
         pass

def connect_lk(productKey,deviceName,deviceSecret):
   """
   @description  : 通过物联网平台连接千里传音服务
   ---------
   @param        : 空
   -------
   @Returns      : 空
   -------
   """
   global on_request, on_play, on_connect
   # 初始化linkkit sdk
   key_info = {
      'region' : 'cn-shanghai' ,
      'productKey': productKey ,
      'deviceName': deviceName ,
      'deviceSecret': deviceSecret ,
      'productSecret': ""
   }
   device = iot.Device(key_info)

   device.on('connect',on_connect)
   # 设置service 事件接收函数(本案例是千里传音)
   device.on('service',on_service)
   # 连接物联网平台
   device.connect()
   # 触发linkit sdk持续处理server端信息
   while(True):
      time.sleep(0.2)
      if  on_request:
            download_resource_file(on_request,resDir)
            on_request = False
      elif on_play:
            play_voice(on_play,resDir)
            on_play = False


if __name__ == '__main__':
   # 初始化音频驱动
   init_audio()
   # 播放开机提示音
   play(tonepathPowerOn)
   # 连接WiFi
   connect_wifi(ssid,pwd)
   # 连接物联网平台
   connect_lk(productKey,deviceName,deviceSecret)
   # 断开连接,释放播放器
   device.close()
   player.stop()
   player.release()

以上是Python轻应用的主体代码,它的主要功能如下:

  1. 初始化音频驱动,播放开机提示音

  2. 连接wifi网络

  3. 连接物联网平台

  4. 监听SpeechPost 服务,下载服务端推送过来的音频文件到 /sdcard/resource/

  5. 监听SpeechBroadcast服务,播放指定的音频

注意事项

  1. 下载常用本地音频资源文件到/sdcard/resource目录 <<资源文件下载>>

  2. 请务必将代码中的wifi热点信息和三元组信息替换

    ssid = “xxxxxxx”

    pwd = “xxxxxxx”

    productKey = “xxxxxxx”

    deviceName = “xxxxxxx”

    deviceSecret = “xxxxxxx”

如何实现

固件烧录

请参考Python轻应用快速上手 中烧录相关章节。

轻应用运行

1.将资源文件拷贝到sdcard中,设备插入sdcard后重启。 2. 将python 代码通过IDE推送到设备中,重启设备后自动运行

SDK调用

  1. 安装SDK核心库

pip install aliyun-python-sdk-core
  1. 修改如下Python代码中的KeyID 和 Secret,并保存为SpeechByCombination.py

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
from aliyunsdkcore.client import AcsClient
from aliyunsdkcore.request import CommonRequest
# 导入自己的accessKeyId 和accessSecret
from aliyun_key import *
client = AcsClient(accessKeyId, accessSecret, 'cn-shanghai')

request = CommonRequest()
request.set_accept_format('json')
request.set_domain('iot.cn-shanghai.aliyuncs.com')
request.set_method('POST')
request.set_protocol_type('https') # https | http
request.set_version('2018-01-20')
request.set_action_name('SpeechByCombination')

request.add_query_param('RegionId', "cn-shanghai")
request.add_query_param('CombinationList.1', "welcome")
# request.add_query_param('CombinationList.1', "zfbGet")
# request.add_query_param('CombinationList.2', "{$10000.056}")
# request.add_query_param('CombinationList.3', "yuan")
request.add_query_param('ProductKey', "a1Ba4rCO9iM")
request.add_query_param('DeviceName', "py_voice_01")

response = client.do_action(request)
# python2:  print(response)
print(str(response, encoding = 'utf-8'))
  1. 执行命令行

    python SpeechByCombination.py