如何在Dialogflow中获得位置和地理坐标的用户确认? [英] How to get user confirmation for Location and the geo-coordinates in Dialogflow?

查看:102
本文介绍了如何在Dialogflow中获得位置和地理坐标的用户确认?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用对话框流程为Google助手制作应用程序。我的应用程序使用部署在firebase上的webhook函数。主要问题是如何获取用户位置-我需要将坐标传递给URL。我可以提示输入位置信息,但是如何确认和获取坐标。

I am making app for google assistant using dialog flow. My app uses a webhook function deployed on firebase. Main question is how to get user location - I need to pass the coordinates to a URL. I am able to prompt the message for location permission, but how to confirm and get coordinates.

我需要添加任何确认意图吗?我在默认的欢迎意图中要求位置许可。

Do I need to add any intent for confirmation? I am asking for location permission in default welcome intent.

代码如下:

'use strict';

process.env.DEBUG = 'actions-on-google:*';
const App = require('actions-on-google').DialogflowApp;

const functions = require('firebase-functions');



//----global variables-----
const http = require('https');
var body = "";
var body2="";
var address="";
var latitude="";
var longitude="";
var lati="";
var long="";


//------ADDRESS_ACTION to tell the current address based on current coordinates----
const ADDRESS_ACTION = 'address_action';

//-----DIRECTION_INTENT to output the map guidence through basic card------
const DIRECTION_INTENT = 'direction_action';

//--------during welcome intent, ask the permiisions------
const DIR_PERMISS_CONF= 'intent.welcome';

exports.addressMaker = functions.https.onRequest((request, response) => {
  const app = new App({request, response});
  console.log('Request headers: ' + JSON.stringify(request.headers));
  console.log('Request body: ' + JSON.stringify(request.body));


  function welcomeIntentDirection (app) 
  {
    app.askForPermission("Hi! Welcome to !To show address/direction",app.SupportedPermissions.DEVICE_PRECISE_LOCATION);
    if (app.isPermissionGranted()) 
    {
     // app.tell('You said ' + app.getRawInput());
    }
    else
    {
     // app.tell('You said ' + app.getRawInput());
    }

  }



function makeDirection(app)
{

  //-------here we are extraction what user said, we will extract the place name, it is for "direction to PLACE_NAME"-------

  var stringRequest=JSON.stringify(request.body);
  var jsonRequest=JSON.parse(stringRequest);
  var jsonSpeech=jsonRequest.originalRequest.data.inputs[0].rawInputs[0].query;
  var arr=jsonSpeech.split("to");
  var placeName=arr[1].trim();

  //------Current Location--------------
  let deviceCoordinates = app.getDeviceLocation().coordinates;
  latitude=deviceCoordinates.latitude;
  longitude=deviceCoordinates.longitude;



//-----now send this place name to api to get coordinates-----
 var req2= http.get("https://api.url-with-PARAMETER-placeName",function(res){

  res.on("data", function(chunk2){ body2 += chunk2;  });
  res.on('end', function()
  {
    if (res.statusCode === 200) 
    {
      var data2 = JSON.parse(body2);

      try
      {
          lati=data2.geometry.lat;
          long=data2.geometry.lng;
      }catch(e){app.tell("Invalid or non-existent address");}    
    }
  });
});


//-------------------Here BUILDING the CARD (Rich RESPONSE)-----------------------
  app.ask(app.buildRichResponse()
    // Create a basic card and add it to the rich response
    .addSimpleResponse('Your directions are here:')
    .addBasicCard(app.buildBasicCard()

      .addButton('Start Guidence', 'https://www.google.com/maps/dir/?api=1&origin='+latitude+','+longitude+'&destination='+lati+','+long+'')
      .setImage('https://png.pngtree.com/element_origin_min_pic/16/11/30/a535f05d9d512610e25a036b50da036f.jpg', 'Image alternate text')
      .setImageDisplay('CROPPED')
  )
);

}


  function makeAddress (app) 
      {
        let deviceCoordinates = app.getDeviceLocation().coordinates;
        latitude=deviceCoordinates.latitude;
        longitude=deviceCoordinates.longitude;
        var req=http.get("https://api.url/reverse?coords="+latitude+","+longitude+"", 
        function(res)
        {
          res.on("data", function(chunk){ body += chunk;  });

          res.on('end', function()
          {
            if (res.statusCode === 200) 
            {
                try 
                {
                  var data = JSON.parse(body);
                  address=data.words;
                  app.tell('Alright, your address is '+address);
                } catch (e) { }
            }
            else 
            {
              app.tell("Unable to contact to server +"+res.statusCode);
            }

          });

        });
      }

  // d. build an action map, which maps intent names to functions
  let actionMap = new Map();
  actionMap.set(DIR_PERMISS_CONF,welcomeIntentDirection);
  actionMap.set(ADDRESS_ACTION, makeAddress);
  actionMap.set(DIRECTION_INTENT, makeDirection);



app.handleRequest(actionMap);
});


推荐答案

是的,您需要一个Intent来处理来自用户。 Dialogflow的模型是来自用户的所有响应都需要通过意图来处理。

Yes, you need an Intent to handle the response from the user. The model of Dialogflow is that all responses from the user need to be handled via an intent.

在这种情况下,这就是您的确认意图。

In this case, it would be your "confirmation" Intent.

您没有显示Intent的屏幕截图(如果您还有其他问题,请更新问题以将其包括在内),但是它需要处理事件 actions_intent_PERMISSION 。处理此事件时,您不需要任何培训短语。

You don't show a screen shot of the Intent (if you have further problems, please update the question to include it), but it needs to handle the Event actions_intent_PERMISSION. When handling this Event, you don't need any training phrases.

我所拥有的一个(意图名称和Action为 result.location )如下:

One that I have (with an Intent name and Action of result.location) looks like this:

作为旁注,在处理程序中,您尝试获取用户名,但是除非您征得其许可,否则该名称不可用。您没有请求许可。如果需要,您可以在询问其位置的同时请求许可,例如

As a side note, in your handler, you're trying to get the user name, but this name isn't available unless you've asked for permission for it. You didn't ask for permission. If you wanted to, you could ask for permission at the same time you asked for their location with something like

app.askForPermissions("To show your address", [
  app.SupportedPermissions.NAME,
  app.SupportedPermissions.DEVICE_PRECISE_LOCATION
]);

更新根据您的屏幕截图。

目前尚不清楚您的对话流程是什么意思,因此我在作一些假设。

It isn't clear what your conversation flow is meant to be, so I'm making a few assumptions.

但是根据您的代码,您是由于欢迎意图而寻求许可的。然后,用户授予权限,您需要一个接受该答复的意图。

But based on your code, you're asking for permission as a result of the Welcome intent. The user then gives permission, and you need an intent that accepts that reply.

我没有看到接受该答复的意图。

I don't see an intent that accepts that reply.

要接受回复,您需要一个处理事件 actions_intent_PERMISSION 的I​​ntent,如上面的屏幕截图所示。

In order to accept the reply, you need an Intent that handles the Event actions_intent_PERMISSION, as I illustrated in my screen shot above.

您还似乎在创建上下文,尽管不清楚原因。

You also seem to be creating Contexts, although it isn't clear why.

更新 >根据您发布的代码和您的其他注释。

Update based on the code you posted and your additional comments.

该代码存在多个问题,可能会导致您遇到一些问题,以及其他一些问题将来可能会引起问题的问题。要在评论中回答您的某些问题以及一些尚未提出的问题:

There are several issues with the code which may be causing some of the problems you're experiencing, and some other issues which may cause you problems in the future. To answer some of your questions in the comments and some unasked questions:

我已启用Small Talk

这并没有伤害任何东西-但也可能没有任何帮助。我建议您禁用它,直到您开始对话的核心部分为止。

This isn't hurting anything - but it probably isn't helping anything either. I would suggest you disable it until you get the core part of your conversation working.

我可以获取坐标

很好-这样Intent起作用了。

Good - so that Intent is working.

但是...

我看到您正在将坐标存储在全局变量中。在这种情况下,这种方法有效(但不完全是,请参见您的下一个问题),但是如果有多个人使用该操作,则不会扩展,因为这些值可能会在用户会话之间混合。

I see that you're storing the coordinates in a global variable. That works in this case (but not quite, see the next question of yours), but won't scale if more than one person is using the action since the values could be mixed up in between user sessions.

换句话说:如果在Webhook中使用全局变量,则每个人都可以访问这些值。这很不好。

您想要的是一种在两次Webhook通话之间存储用户信息的方法。 其他地方涵盖了很多方法,并且可以涉及很多方法。但是,通常,您可以将值存储在上下文中或 app.data 中,它们将作为同一对话的一部分返回给您。

What you want is a way to store user information in between calls to your webhook. There are a number of ways to do this that are covered elsewhere and can be rather involved. In general, however, you can store the values in either a context or in app.data and they will be returned to you as part of the same conversation.

当我第一次询问时我没有目的地地址

当我再次询问时,它具有目标地址

您的函数 makeDirection()包含一个异步操作来获取目标地址的纬度/经度,但是您是在异步块之外发回答复。

Your function makeDirection() contains an asynchronous operation to get the lat/lon of the destination address, however you're sending back the reply outside of that asynchronous block.

所以发生的事情是启动了http调用,然后代码继续,然后您将答复发送给目的地为空的用户。在稍后的某个时刻,回调完成并设置了目的地,但是对于第一次调用而言为时已晚。但是,当您第二次调用它时,它会通过相同的例程(启动异步调用,然后在调用完成之前立即发送回一些东西),但是设置了上一次运行的值,因为您已经在全局变量中设置了它们。

So what happens is that you start the http call, and then the code continues and you send the reply to the user with the empty destination. At some later point, the callback completes and the destination is set, but too late for the first call. But when you call it the second time, it goes through the same routine (starts the async call, and then immediately sends something back before the call completes), but the values from the previous run are set because you had set them in global variables.

要解决此问题,您需要调用 app.ask()作为您的一部分异步回调。可能看起来像这样:

To fix this, you're going to need to call app.ask() as part of your async callback. This might look something like this:

http.get("https://api.url-with-PARAMETER-placeName",function(res){

  res.on("data", function(chunk2){ body2 += chunk2;  });
  res.on('end', function(){
    if (res.statusCode === 200){
      var data2 = JSON.parse(body2);

      try{
        lati=data2.geometry.lat;
        long=data2.geometry.lng;
        app.ask( 
          app.buildRichResponse()
            .addThingsToRichResponse()
        );
      } catch(e){
        app.tell("Invalid or non-existent address");
      }
    }
  });
});

关于获取用户对目的地的评价的问题

您试图获取用户目的地的代码很奇怪。获取 rawInputs 是合法的,但尝试将其拆分以获取特定值并不是最佳做法,尤其是因为用户可能无法准确地说出您的想法说。例如,如果他们说我要去某个地方

Your code where you're trying to get the user's destination is... strange. Getting the rawInputs is legal, but trying to break it apart to get specific values isn't best practice, especially since the user might not say exactly what you think they're going to say. For example, what if they said "I'm heading towards somewhere".

最好是让您的 direction_action 意向采用各种不同的短语,并将其(目标)的重要部分分配给参数。然后,在您的Webhook中,您可以仅读取参数的值并将其传递给服务以确定位置。

Better is to have your direction_action Intent take a variety of different phrases and assign the "important" part of that (the destination) to a parameter. Then, in your webhook, you can read just the value of the parameter and pass that to the service to determine the location.

您还可能希望看看最近宣布的 Place Helper ,它类似于设备的精确位置帮助器,而且还会获得用户指定的地址。

You also may wish to take a look at the recently announced Place Helper, which is similar to the device precise location helper, but also gets an address that the user specifies.

这篇关于如何在Dialogflow中获得位置和地理坐标的用户确认?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆