简体   繁体   English

即使没有参数值,Google API.ai webhook也会触发node.js调用

[英]Google API.ai webhook post firing node.js call even without parameter value

Ive got a working Google API.ai project that I speak to, ask it to turn on a component, it posts the json to a webhook URL and my nodejs parses the json to carry out a python script on a raspberry. 我有一个正在工作的Google API.ai项目,我要说该项目,要求它打开一个组件,将json发布到webhook URL,我的nodejs解析json以在树莓派上执行python脚本。 The problem is that apparently just calling the welcome intent fires the json post and toggles python script to turn on the component. 问题是,显然只是调用welcome意图会触发json帖子并切换python脚本以打开该组件。 The strange thing i that the state-of-component required by the if-statement to determine which python script to call is empty at the welcome intent state. 奇怪的是,if语句确定要调用哪个python脚本所需的组件状态在欢迎意图状态下为空。

This is my node.js: 这是我的node.js:

'use strict';
require('dotenv').config();

const PythonShell = require('python-shell');
const fs = require('fs');
const express = require('express');
const bodyParser= require('body-parser');
const path = require('path')
const app = express();

process.env.DEBUG = 'actions-on-google:*';
let Assistant = require('actions-on-google').ApiAiAssistant;
app.use(bodyParser.json({type: 'application/json'}));

const GENERATE_ANSWER_ACTION = 'generate_answer';
const EXECUTE_HOME_COMMAND = 'execute_home_command';

const switches = [];

var readableStream = fs.createReadStream('saveState.json');
var data = ''

readableStream.on('data', function(chunk) {
    data+=chunk;
});

readableStream.on('end', function() {
  var parsed = JSON.parse(data);
  for (var i=0;i<parsed.switches.length;i++){
    switches.push(new Switch(parsed.switches[i]))
  }
});

function Switch(switchValues){
  this.id = switchValues.id || "sw"
  this.state = switchValues.state || "off"
  this.name = switchValues.name || "switch"
  this.toggle = function(){
    if(this.state === "on"){
      this.setState("off")
    } 
    else{
      this.setState("on");
    }
  }
  this.setState = function(state){
    var str = state === "on" ? onString(this.id[2]) : offString(this.id[2]);
    PythonShell.run(str, function (err) {
      if (!process.env.DEV){
        if (err) throw err;
      } 
    });
    this.state = state
  }
  this.setState(this.state);
}    

function onString(number){
  return './public/python/sw' + number + '_on.py'
}
function offString(number){
  return './public/python/sw' + number + '_off.py'
}

function getSwitch(string){
  return switches.filter(function(element){
    return element.id === string;
  })[0]
}

function saveState (){
  var formattedState = {
    switches: switches
  }
  fs.writeFile('./saveState.json', JSON.stringify(formattedState) )
}

app.use(bodyParser.urlencoded({ extended: true }))
app.use(express.static(__dirname + '/public'));

app.get('/', function(req, res){
  res.sendFile('index');
})

// Switch Routes for API
app.get('/api/switches', function(req, res){
  res.send(switches);
})

app.get('/api/switches/:id', function(req, res){
  var found = getSwitch(req.params.id);
  res.json(found);
})

app.post('/api/switches/:id', function(req, res){
   console.log('headers: ' + JSON.stringify(req.headers));
   console.log('body: ' + JSON.stringify(req.body));
   const assistant = new Assistant({request: req, response: res});
   let soc = assistant.getArgument('state-of-component')

   function generateAnswer(assistant) {
      console.log('genera answer');
      assistant.ask('I\'m thinking of a number from 0 and 100. What\'s your first guess?');
   }

   function executeHomeCommand(assistant) {
    console.log('revisear guess');
    console.log(soc);
    if (soc === "on") {
       console.log('SUCCESS soc=ON');
    } else {
        console.log('FAILUER soc=OFF');
    }
    }
//   //MAP ACTIONS to functions
      let actionMap = new Map();
      actionMap.set(GENERATE_ANSWER_ACTION, generateAnswer);
      actionMap.set(EXECUTE_HOME_COMMAND, executeHomeCommand);
      assistant.handleRequest(actionMap);

  if (req.query.password === process.env.PASS){
    var foundSwitch = getSwitch(req.params.id);

    if (soc === "on") {
        foundSwitch.setState("on");
        console.log('SWITCHING ON');
    } else {
        foundSwitch.setState("off");
        console.log('SWITCHING OFF');
    }

    saveState();
    console.log("postSwitch "+JSON.stringify(foundSwitch));
    res.json(foundSwitch);
  }
  else {
    console.log("invalid password")
    res.send("try again")
  }

})

app.listen(process.env.PORT, function(){
 console.log('Listening on port ' + process.env.PORT);
})

I thought it was my app.js code making the post on the welcome intent but Im not so sure, because on the welcome intent, the state-of-component is empty, no value, so soc is != "on", so the if statement is working properly. 我认为这是我的app.js代码根据欢迎意图进行发布的,但我不太确定,因为根据欢迎意图,组件状态为空,没有任何值,因此soc为!=“ on”,因此if语句正常工作。 The problem is that the: 问题是:

if (soc === "on") {
        foundSwitch.setState("on");
        console.log('SWITCHING ON');

code is being called on the welcome intent as well and it shouldnt. 代码也在欢迎意图上被调用,因此不应该。

Well, the real problem is that you seem to be doing processing for all intents instead of specific things based on specific intents. 好吧,真正的问题是您似乎正在对所有意图进行处理,而不是根据特定意图进行特定处理。 With API.AI, you have two ways to handle this: 使用API​​.AI,您可以通过两种方式处理此问题:

  1. You can always turn webhook resolution off for a particular Intent, and still leave it on for other Intents. 您始终可以为特定的Intent关闭webhook解析,而对于其他Intent仍然保持打开状态 In this case, you could leave it off for your welcome intent (which would send a greeting prompt and so forth), but turn it on for other command processing. 在这种情况下,您可以出于欢迎目的而将其关闭(这将发送问候提示等),但是将其打开以进行其他命令处理。

  2. Once your webhook is called, the actions-on-google library determines the specific function to call for the Action that it was called for. 调用您的Webhook后,Google动作库将确定调用该动作所要使用的特定函数。 This is handled via the assistant.handleRequest(actionMap); 这是通过assistant.handleRequest(actionMap);处理的assistant.handleRequest(actionMap); line. 线。

In your code, you have additional processing happening after the call to assistant.handleRequest(actionMap); 在您的代码中, assistant.handleRequest(actionMap);的调用之后 ,您将进行其他处理assistant.handleRequest(actionMap); . So this additional code is being processed for every call. 因此,正在为每个调用处理此附加代码。 It sounds like this isn't what you want. 听起来这不是您想要的。

You should move this code into specific Action processing code that is registered with the actionMap. 您应该将此代码移到在actionMap中注册的特定Action处理代码中。 (I don't know what your actions are, but I assume placing the code just in the executeHomeCommand() function would make the most sense, assuming everything else is hooked up correctly.) (我不知道您的操作是什么,但我假设将所有其他代码正确地连接在一起,将代码仅放在executeHomeCommand()函数中是最有意义的。)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM