Actions API.ai sur Google – Échec d’parsing de la chaîne de réponse JSON avec l’erreur ‘INVALID_ARGUMENT’: “: Champ introuvable.”

Cette erreur est similaire à celle que j’ai posée ici , mais cette fois-ci c’est avec le client NodeJs.

J’essaie de trouver un itinéraire. Dès que l’intention est déclenchée sur mon compte Web, je calcule les instructions à l’aide de GoogleMapAPI. Mais avant qu’il puisse terminer et envoyer une réponse, je reçois le message d’erreur sur ma console Actions.

J’ai vérifié le temps de réponse total et il rest moins de 2 secondes, ce qui correspond à un délai d’expiration inférieur à 5 secondes par Google.

Où je me trompe ???

Mon intention API.ai
entrez la description de l'image ici entrez la description de l'image ici

Utilisation de express.js avec le client Action-on-Google Node

'use ssortingct'; const express = require('express'); const bodyParser = require('body-parser'); const intentHandler = require('./intent_handler') const app = express(); app.use(bodyParser.json()); const ApiAiAssistant = require('actions-on-google').ApiAiAssistant; // Create functions to handle requests here .... .... const DIRECTION_INTENT = 'action_direction'; function MyAssistant(req, res) { const assistant = new ApiAiAssistant({request: req, response: res}); assistant.handleRequest(responseHandler(assistant)); } function responseHandler (assistant) { // intent contains the name of the intent you defined in the Actions area of API.AI let intent = assistant.getIntent(); switch (intent) { case WELCOME_INTENT: ... break; case WELCOME_FALLBACK_PERMISSION_INTENT: ... break; case DIRECTION_INTENT: console.log(">>>>>>>DIRECTION_INTENT<<<<<<<"); intentHandler.directionIntent(assistant); break; } } app.post('/', function (req, res) { MyAssistant(req, res); }); app.listen(8080, function () { console.log('app listening on port 8080!') }); 

Code de gestionnaire

 'use ssortingct'; const speech = require("./speech_template"); const direction = require("./directionModule"); const intent_handler = { 'welcomeIntent': function (assistant) { ..... }, 'welcomeFallbackPermissionIntent': function (assistant) { ..... }, 'directionIntent':function (assistant) { console.log('direction intent'); direction.getDirectionWithSavedAddress(function (response) { assistant.ask(response); }); } }; module.exports = intent_handler; 

Direction Extraction — ERROR vient sur Action Console avant que cela soit terminé

 'use ssortingct'; const ssortingptags = require('ssortingptags'); const speech = require("./speech_template"); let googleMapsClient = require('@google/maps').createClient({ key: global.GOOGLE_DIRECTION_KEY }); const directionModule = { 'getDirectionWithSavedAddress': function (eventCallback) { let myAdd = ; if (myAdd === undefined) { console.log("error......"); } let destination = ; this.getDirectionWithAddress(myAdd, destination, function (dir) { .... if(SUCCESS){ eventCallback(` ${steps} `); }else{ eventCallback(` ${speech.ERROR_DIRECTIONS} `); } }); }, 'getDirectionWithAddress': function (add1, add2, eventCallback) { let dir = {}; googleMapsClient.directions({ origin: add1, destination: add2, mode: "driving", departure_time: "now" }, function (err, response) { if (!err) { console.log(response.json.routes[0]); .... .... .... } else { console.log(`Error --> ${err.toSsortingng()}`); .... } eventCallback(dir); }); } }; module.exports = directionModule; 

UPDATE J’utilise le code localement via WebStorm et expose Webhook via un transfert de port à l’aide de ngrok.

Mise à jour2
MAUVAISE DEMANDE 400

entrez la description de l'image ici

 { "originalRequest": { "source": "google", "version": "2", "data": { "isInSandbox": true, "surface": { "capabilities": [ { "name": "actions.capability.AUDIO_OUTPUT" } ] }, "inputs": [ { "rawInputs": [ { "query": "get me there", "inputType": "VOICE" } ], "arguments": [ { "rawText": "get me there", "textValue": "get me there", "name": "text" } ], "intent": "actions.intent.TEXT" } ], "user": { "locale": "en-US", "userId": "" }, "device": {}, "conversation": { "conversationId": "", "type": "ACTIVE", "conversationToken": "[\"_actions_on_google_\",\"defaultwelcomeintent-followup\"]" } } }, "id": "", "timestamp": "2017-09-12T17:08:10.321Z", "lang": "en", "result": { "source": "agent", "resolvedQuery": "get me there", "speech": "", "action": "action_direction", "actionIncomplete": false, "parameters": {}, "contexts": [ { "name": "_actions_on_google_", "parameters": {}, "lifespan": 99 }, { "name": "google_assistant_input_type_voice", "parameters": {}, "lifespan": 0 }, { "name": "actions_capability_audio_output", "parameters": {}, "lifespan": 0 }, { "name": "defaultwelcomeintent-followup", "parameters": {}, "lifespan": 4 } ], "metadata": { "intentId": "", "webhookUsed": "true", "webhookForSlotFillingUsed": "false", "nluResponseTime": 15, "intentName": "DirectionIntent" }, "fulfillment": { "speech": "", "messages": [ { "type": 0, "speech": "" } ] }, "score": 1 }, "status": { "code": 200, "errorType": "success" }, "sessionId": "" } 

Cela ressemble à avant que mon rappel ne soit terminé, mon Webhook envoie une réponse vide à Google Actions.
Pourquoi cela se passe-t-il et comment le résoudre ?????

Le problème réside dans la façon dont votre fonction directionIntent() appelle et gère le résultat de votre fonction getDirectionWithSavedAddress() . Il s’attend à getDirectionWithSavedAddress() que getDirectionWithSavedAddress() retourne une fonction, alors que ce n’est pas le cas. getDirectionWithSavedAddress() s’attend à envoyer ses résultats à un rappel .

Ainsi, après avoir appelé getDirectionWithAddress() , la fonction se termine sans rien retourner. Ce “rien” est envoyé à assistant.ask() , qui le renvoie au serveur de Google. Ceci est une réponse invalide, vous obtenez donc l’erreur.

La fixation devrait être simple. Vous devez appeler getDirectionWithSavedAddress() avec une fonction de rappel. Dans cette fonction, vous devez appeler assistant.ask() avec la valeur envoyée au rappel.

Donc directionIntent() pourrait ressembler à quelque chose comme

  'directionIntent':function (assistant) { console.log('direction intent'); direction.getDirectionWithSavedAddress( function( msg ){ assistant.ask( msg ); } ); } 

Mis à jour

Cette ligne n’a aucun sens:

 assistant.handleRequest(responseHandler(assistant)); 

La fonction assistant.handleRequest() est supposée recevoir une carte de noms d’intention aux fonctions à appeler pour gérer l’événement. Vous le faites manuellement dans la fonction responseHandler() et vous ne retournez pas de carte. Puisque vous ne retournez pas de handleRequest() , elle échoue lorsque vous essayez d’ handleRequest() la fonction handleRequest() et génère le handleRequest() erreur “Action Erreur: le gestionnaire de demandes ne peut PAS être vide”.

Vous pouvez résoudre ce problème en appelant simplement responseHandler(assistant) et en ne traitant pas du tout avec handleRequest() . Vous pouvez également créer la carte handleRequest() par handleRequest() et supprimer complètement responseHandler() .