Android Things 智能音箱教程:创建 Google Assistant 控制的 Android Things 设备

介绍

Google Assistant 和其他自然语言理解平台正在推动用户如何使用他们的技术。无论是执行器诸如设置计时器之类的简单任务,还是进行更复杂的任务(例如 Google 智能助理调整恒温器),您都可以参与其中。在这篇文章中,我们将逐步介绍如何构建自己的助手应用程序,通过简单地要求 Google 来控制 Android Things 设备来浇灌植物。

Android的东西外设

此应用程序演示的 Android Things 设备有两个目的。首先是接受 Google Assistant 的命令,说出我在之前的博客文章中显示的 “Hey CapTech Assistant”。其次是打开和关闭任何 Google 智能设备收到的 Google Action 命令中的水泵。两种功能都可以彼此独立使用,但重要的是要了解,您可以构建由 “Assistant” 控制的自定义设备,向 “Assistant” 发出请求,或者两者兼而有之。

此演示应用程序的基础部分,构建于我之前的博客文章上。在那篇文章中,我解释了如何连接指示用户正在进行 Assistant 请求的指示灯。有关照明和 GPIO 外围设备使用的更多信息,请查看我的同事关于此主题的文章

对于这篇文章,我们有一个额外的 GPIO 引脚用于控制泵。该泵是一个 DC 12V 蠕动泵,可在亚马逊上找到。该泵至少需要 12V 电源,因此我们将使用外部电源为泵供电。为了使用 Android Things 设备打开和关闭泵,我们将使用 5V 继电器模块。

要将泵连接到继电器,您需要将电源的零线连接到泵的一端,然后将另一根线从泵的另一端连接到继电器的左侧,如下图所示。当 Android Things 设备翻转继电器时,电路完成并且泵将启动 - 这很像您家中的电灯开关。

继电器

下面是关于继电器和树莓派的附加演示应用程序使用的常用接线。

Assistant 连线

Firebase 数据库

附带的演示应用程序中,我们将使用 Firebase 实时数据库将我们的泵与 Google Assistant 同步,以便我们的操作可以打开和关闭一段时间的水。

为了开始使用,请使用以下 JSON 结构设置 Firebase 数据库:

{
  "bonsai_status" : {
    "some_id" : {
      "status_date" : 0,
      "watering" : false,
      "watering_duration" : 0
    }
  }
}

一旦您创建了 Firebase 实时数据库,为了我们的应用程序的目的,我们将关闭身份验证要求。为此,请选择 “Rule” 选项卡并执行以下规则:

{
  "rules": {
    ".read": "true",
    ".write": "true"
  }
}

接下来,我们准备将 Firebase 引用(reference)添加到我们的 Android Things 应用程序。

首先,我们需要将相应的框架添加到我们的 build.gradle 文件中。

compile 'com.google.firebase:firebase-core:11.0.4'
compile 'com.google.firebase:firebase-database:11.0.4'

接下来,在 CapTechAssistant Activity 中获取对 Firebase 数据库的引用。

FirebaseDatabase assistantDatabase = FirebaseDatabase.getInstance();
DatabaseReference bonsaiData = assistantDatabase.getReference("bonsai_status");

最后,我们希望听取何时将新的子对象(children)添加到我们的 bonsai_status 数据库。 任何时候添加一个新的 children,我们的回调将被击中,我们将相应地打开或关闭我们的泵。

bonsaiData.addChildEventListener(new ChildEventListener() {
    @Override
    public void onChildAdded(DataSnapshot dataSnapshot, String s) {
        currentStatus = BonsaiStatus.getStatusFromSnapShot(dataSnapshot);
        pump.toggleGPIO(currentStatus.watering);
            if (wateringTimer != null) {
                wateringTimer.cancel();
                wateringTimer = null;
            }

            if (currentStatus.watering) {
                //water for a specific amount of time.
                wateringTimer = new CountDownTimer(currentStatus.watering_duration*1000, currentStatus.watering_duration) {
                    @Override
                    public void onTick(long millisUntilFinished) {

                    }

                    @Override
                    public void onFinish() {
                        wateringTimer.cancel();
                        pump.toggleGPIO(false);
                        wateringTimer = null;

                        //once we are done, let Firebase know
                        BonsaiStatus stopStatus = new BonsaiStatus();
                        stopStatus.watering = false;
                        stopStatus.statusDate = System.currentTimeMillis();
                        stopStatus.watering_duration = 0;
                        bonsaiData.push().setValue(stopStatus);
                    }
                };
                wateringTimer.start();
            }   
    }

    @Override
    public void onChildChanged(DataSnapshot dataSnapshot, String s) {
        //not using
    }

    @Override
    public void onChildRemoved(DataSnapshot dataSnapshot) {
        //not using
    }

    @Override
    public void onChildMoved(DataSnapshot dataSnapshot, String s) {
        //not using
    }

    @Override
    public void onCancelled(DatabaseError databaseError) {
        //not using
    }
});

API.AI

现在我们的 Android Things 设备已设置为与我们的 Firebase 实时数据库同步,现在我们准备开始设置 Google Assistant 操作。 为此,我们将利用 API.AI 来处理用户语音命令。要开始使用,我强烈建议您推荐我的同事的博客,撰写您的第一个 API.AI.

对于我们的行动,我们将设立3个意图。

Welcome

Welcome 意图用于询问用户调用您的操作后他们想要做什么。我们的 Welcome 意向不会有任何行动。当我们的 Welcome 意向受到影响时,它会通过我们的四个建议答复之一向用户做出回应,询问用户他们接下来会做什么。

welcome intent

在上面的图片中,您会注意到 “end conversation” (结束对话)框未被选中,并且我们的助理设备会向用户指示应答。

Watering

当用户要求我们的行动为他们的植物浇水时,浇水(Watering)的意图就会受到打击。 浇水意图将回应用户可以提出的许多预定请求之一。 意图还期望用户指定持续时间来浇灌植物。为此,我们将突出显示我们预先确定的用户请求的区域,并指出它们是 “duration” (持续时间)参数。

浇水时间

由于我们的意图期望持续时间,因此我们需要提示用户他们是否提出了符合我们意图的请求,但他们没有指明持续时间。为此,我们将为我们的持续时间参数添加提示。

持续时间提醒

接下来,我们将指出一些适用于用户请求的响应,并通过检查 “end conversation” (结束对话)框让 Action 知道用户不再有任何请求。

持续时间响应

Stop Watering

停止浇水(Stop Watering)的意图,就像它的名字一样。当用户表示他们想要关闭水泵时触发。 再次,我们将输入一些预定义的用户请求,助理响应,并向 Action 表明我们不期望用户的后续响应。

Context

设置意图时,您会发现用于输入用户请求的上下文的框。 上下文用于指示额外的数据,这对用户未来的请求可能会有帮助。为了我们的目的,上下文不是必需的。

Testing API.AI

您可以随时通过在 API.AI 控制台的右窗格中,键入请求来测试 API.AI 意图。您可以确保您的意图响应各种用户请求并做出适当的响应。

Cloud Functions

接下来,我们将启用我们的API.ai处理的用户请求,以启动 Google Cloud function 来更新我们的 Firebase 实时数据库,以打开和关闭我们的 Android Things 泵。为此,我们将使用 Cloud Functions 来托管一些将在 Node.js 环境中运行的 JavaScript。

要开始使用,请下载并安装 Node.js 和 Firebase CLI。如果您尚未安装这些软件,请下载并安装 Node.js 和 Firebase CLI。安装完成后,您应该可以像这样从命令行运行它们来检查它们的版本:

node --version
firebase --version

一般来说,您应该始终确保使用以下命令保持 Firebase CLI 的最新状态:

npm install -g firebase-tools

创建并初始化您的 Cloud Functions 工作区,现在,创建一个文件夹来保存您的项目:

mkdir firebase-assistant-codelab
cd firebase-assistant-codelab

验证并访问您现有的项目:

firebase login

将出现一个窗口请求权限。

firebase init

你现在将有一个 “functions” 目录准备好保存你的代码。有一个默认的 index.js ,它是 Cloud Functions 代码的入口点。打开 index.js 文件进行编辑。

'use strict';

process.env.DEBUG = 'actions-on-google:*';

const Assistant = require('actions-on-google').ApiAiAssistant;
const functions = require('firebase-functions');
const admin = require('firebase-admin');
admin.initializeApp(functions.config().firebase);

const bonsaiStatus = admin.database().ref('bonsai_status');

// API.AI Intent names
const WATER_INTENT = 'water-duration';
const STOP_INTENT = 'stop-watering';

// Contexts
const WATER_CONTEXT = 'water_duration';
const STOP_CONTEXT = 'stop';

// Context Parameters
const DURATION_PARAM = 'duration';
const FULFILLMENT_PARAM = 'fulfillment';

exports.assistantcodelab = functions.https.onRequest((request, response) => {
    const assistant = new Assistant({request: request, response: response});

    let actionMap = new Map();
    actionMap.set(WATER_INTENT, water);
    actionMap.set(STOP_INTENT, stop)
    assistant.handleRequest(actionMap);

    /**
    *Code to start the watering process
    **/
    function water(assistant) {

        var d = new Date();
        var n = d.getTime();

        const duration = assistant.getContextArgument(WATER_CONTEXT, DURATION_PARAM).value;

        const numberTime = duration.amount;
        const unitTime = duration.unit;


        var timeInSeconds = 120;//default

        switch(unitTime){
            case "h":
                timeInSeconds = numberTime *60*60;
                break;
            case "s":
                timeInSeconds = numberTime;
                break;
            default:
                timeInSeconds = numberTime * 60;//default to unit being minutes
                break;
        }

        var currentStatus = {
            'status_date': 0,
            'watering': true,
            'watering_duration': 120
        };
        currentStatus.status_date = n;
        currentStatus.watering_duration = timeInSeconds;
        bonsaiStatus.push().set(currentStatus);
        assistant.tell(request.body.result.fulfillment.speech);
    }
    /**
    *Code to stop the watering process
    **/
    function stop(assistant) {
        var d = new Date();
        var n = d.getTime();
        var currentStatus = {
            'status_date': 0,
            'watering': false,
            'watering_duration': 0
        };
        currentStatus.status_date = n;
        bonsaiStatus.push().set(currentStatus);
        assistant.tell(request.body.result.fulfillment.speech);
    }
});

在上面的函数中,您会注意到我们将两个方法映射到可能从助手进入的意图。每种方法都是根据各自的意图调用的。在处理完他们的请求之后,我们会通过 API.AI 提供的响应回复用户。如果您选择,您可以使用自己在 Cloud Function 中生成的一个覆盖该响应。要详细了解您可以使用云端功能做什么,请在此处查找更多信息

完成 index.js 设置后,即可开始部署。为此,通过终端导航到 function 目录并运行以下命令。

npm install --save actions-on-google
``

接下来部署代码:

firebase deploy ```

部署完成后,将显示一个 URL。稍后再继续。

Webhooks

我们现在准备将我们的 Cloud Function 与我们的 API.AI 意图联系起来。要做到这一点,打开浇水和停止浇水的意图,并在 “Fulfillment” 下勾选 “Use Webhook”。

接下来在左侧面板中,找到 “Fulfillment” 选项卡。 输入您在上一步中获得的网址,并确保已启用 webhook 切换。

完成上述操作后,您现在可以像以前一样测试 API.AI 请求,没有意外的话,他们应该启动您的 Cloud Function。 如果遇到问题,可以查看您的 Fulfillment 日志以获取更多详细信息。

集成 Assistant

我们终于准备好开始使用我们的 Google Assistant 的功能。在 API.AI 控制台中,在左侧窗口中选择 “Integrations”。从这里你将能够从各种平台中进行选择。 为了演示的目的,我们将选择 “Actions on Google”。 您将需要授权并链接您的项目。

在您的 Google Actions Console中,您可以设置您的应用程序进行发布。在此之前,您可以启用测试模式,然后才能在任何已启用的助理设备上进行测试,该设备是以 Google Action 的同一所有者身份登录的。

结论

我鼓励你进一步采用这个演示,并添加一个你自己的意图来检查你的设备的当前状态,或者当它最后一次浇灌你的设备时。请查找附件演示应用程序以获取更多信息。

英语原文链接:Building a Google Assistant Controlled Android Things Device

尚未评分
您的评分将帮助我们做出更好的玩法

观光\评论区

Copyright © 2017 玩点什么. All Rights Reserved.