Google Home actions Sync payload issue - json

Below is the payload generated for SYNC intent. When tested in smart home validator it parses the json without any issue.
Sync Response Payload:
{
"payload": {
"agentUserId": "myhome",
"devices": [
{
"traits": [
"action.devices.traits.OnOff"
],
"willReportState": false,
"name": {
"defaultNames": [],
"name": "Sky Light",
"nicknames": []
},
"attributes": [],
"customData": "",
"id": "BED_LIGHT",
"type": "action.devices.types.LIGHT",
"deviceInfo": {
"swVersion": "1.0",
"model": "Light",
"manufacturer": "Connected Smart Life",
"hwVersion": "1.0"
}
},
{
"traits": [
"action.devices.traits.OnOff"
],
"willReportState": false,
"name": {
"defaultNames": [],
"name": "Ruthu Room Round Light",
"nicknames": []
},
"attributes": [],
"customData": "",
"id": "SWITCH94",
"type": "action.devices.types.LIGHT",
"deviceInfo": {
"swVersion": "1.0",
"model": "Light",
"manufacturer": "Connected Smart Life",
"hwVersion": "1.0"
}
}
]
},
"requestId": "18338945788402571764"
}
But, Google Assistant Actions failed to parse this and the log shows below erros:
{
insertId: "1ha0kvhg1kf0a0t"
logName: "projects/connectedghome/logs/actions.googleapis.com%2Factions"
receiveTimestamp: "2018-05-05T21:04:27.318451222Z"
resource: {…}
severity: "ERROR"
textPayload: "SYNC: Request ID 18338945788402571764 update devices failed: INVALID_ARGUMENT. Detail: Error: [Expect a map object but found: []] while parsing JSON [{"payload":{"agentUserId":"myhome","devices":[{"attributes":[],"customData":"","deviceInfo":{"hwVersion":"1.0","manufacturer":"Connected Smart Life","model":"Light","swVersion":"1.0"},"id":"BED_LIGHT","name":{"defaultNames":[],"name":"Sky Light","nicknames":[]},"traits":["action.devices.traits.OnOff"],"type":"action.devices.types.LIGHT","willReportState":false},{"attributes":[],"customData":"","deviceInfo":{"hwVersion":"1.0","manufacturer":"Connected Smart Life","model":"Light","swVersion":"1.0"},"id":"SWITCH94","name":{"defaultNames":[],"name":"Ruthu Room Round Light","nicknames":[]},"traits":["action.devices.traits.OnOff"],"type":"action.devices.types.LIGHT","willReportState":false}]},"requestId":"18338945788402571764"}]"
timestamp: "2018-05-05T21:04:27.284259780Z"
}
Am I missing something here?

Attributes should be a JSON object or not defined.

Related

Change json object with jq

how can I update servers object in my json using jq?
"tags": [],
"servers": [],
"components": {
"securitySchemes": {
"cookie": {
"type": "apiKey",
"in": "cookie",
"name": "store",
"description": "Store API"
}
},
I need to have servers like that:
"servers": [
{
"url": "http://localhost:5000",
"description": "Localhost server"
}
],
echo '{"tags": [],
"servers": [],
"components": {
"securitySchemes": {
"cookie": {
"type": "apiKey",
"in": "cookie",
"name": "store",
"description": "Store API"
}
}
}}' | jq '.servers = [{url:"http://localhost:5000", description: "Localhost server"}]'
Or, for a fixed json file (adding missing }):
jq '.servers = [{url:"http://localhost:5000", description: "Localhost server"}]' file.json

Google actions fails to parse JSON response

I've been struggling with getting an assistant app to respond correctly.
This app is written with Google Actions SDK (there are no other components such as Dialogflow or Converse.ai).
The action package for the app looks something like this:
{
"actions":[
{
"description": "Default Welcome Intent",
"name": "MAIN",
"fulfillment": {
"conversationName": "ACTION_INTENT_MAIN"
},
"intent": {
"name": "actions.intent.MAIN",
"trigger": {
"queryPatterns": [
"talk to gactions integration"
]
}
}
}
],
"conversations":{
"ACTION_INTENT_MAIN": {
"name": "ACTION_INTENT_MAIN",
"url": "https://my.custom.end/point"
}
},
"locate":"en"
}
This is the JSON request that I recieve on https://my.custom.end/pont:
{
"user": {
"userId": "<a-user-id-sent-by-GOOG>",
"locale": "en-US",
"lastSeen": "2018-01-31T09:33:07Z"
},
"conversation": {
"conversationId": "1517393479793",
"type": "NEW"
},
"inputs": [
{
"intent": "actions.intent.MAIN",
"rawInputs": [
{
"inputType": "KEYBOARD",
"query": "Talk to Gactions Integration"
}
]
}
],
"surface": {
"capabilities": [
{
"name": "actions.capability.AUDIO_OUTPUT"
},
{
"name": "actions.capability.SCREEN_OUTPUT"
},
{
"name": "actions.capability.MEDIA_RESPONSE_AUDIO"
},
{
"name": "actions.capability.WEB_BROWSER"
}
]
},
"isInSandbox": true,
"availableSurfaces": [
{
"capabilities": [
{
"name": "actions.capability.AUDIO_OUTPUT"
},
{
"name": "actions.capability.SCREEN_OUTPUT"
}
]
}
]
}
An on the simulator, I end up getting this response: API Version 2: Failed to parse JSON response string with 'INVALID_ARGUMENT' error: ": Cannot find field.".
I can confirm that the incoming request has the google-actions-api-version set to 2.
This is the sharedDebugInfo section from the Actions on Google simulator:
[
{
"name": "ResponseValidation",
"subDebugEntry": [
{
"debugInfo": "API Version 2: Failed to parse JSON response string with 'INVALID_ARGUMENT' error: \": Cannot find field.\".",
"name": "UnparseableJsonResponse"
}
]
}
]
The oh-so-informative error message lacks the name of the field that cannot be found.
And this is when I'm doing everything described here
UPDATE - 01 February, 2018, 11:52 AM
These are the full contents of the debug tab:
{
"audioResponse": "//NExAAQaE...",
"conversationToken": "GidzaW11bG...",
"debugInfo": {
"agentToAssistantDebug": {
"agentToAssistantJson": "{\"conversationToken\":\"{\\\"state\\\":null,\\\"data\\\":{}}\",\"expectUserResponse\":true,\"expectedInputs\":[{\"inputPrompt\":{\"noInputPrompts\":[],\"richInitialPrompt\":{\"items\":[{\"simpleResponse\":{\"textToSpeech\":\"You're now talking to GActions Integration\",\"displayText\":\"You're now talking to GActions Integration\"}},{\"basicCard\":{\"buttons\":[{\"title\":\"Some Reddit to chill\",\"openUrlAction\":{\"url\":\"https://www.reddit.com\"}}],\"formattedText\":\"Here's some simp-wave to relax and chill out to\",\"image\":{\"url\":\"http://tracks.arte.tv/sites/default/files/styles/jscrop_1007x566/public/c_simpsons_2.jpg?itok=INzKpsvK\",\"accessibilityText\":\"A World of Simpsonwave\"},\"title\":\"A World of Simpsonwave\",\"imageDisplayOptions\":\"CROPPED\"}}],\"suggestions\":[]}},\"possibleIntents\":[{\"intent\":\"actions.intent.TEXT\"}]}],\"resetUserStorage\":false,\"userStorage\":\"{}\",\"finalResponse\":null,\"isInSandbox\":true,\"customPushMessage\":null,\"speech\":\"You're now talking to GActions Integration. \",\"displayText\":\"You're now talking to GActions Integration. \"}"
},
"assistantToAgentDebug": {
"assistantToAgentJson": "{\"user\":{\"userId\":\"ABwppHHHw9N9TYh-scJ5GhZtmpfFcQU2xbQBAgW1qhdllI45fimQ5QKFEVRfs2iMm6uCDJIQMApo1UZLmmnif8wqlNARnsVH744\",\"locale\":\"en-US\",\"lastSeen\":\"2018-02-01T06:04:59Z\"},\"conversation\":{\"conversationId\":\"1517465629416\",\"type\":\"NEW\"},\"inputs\":[{\"intent\":\"actions.intent.MAIN\",\"rawInputs\":[{\"inputType\":\"VOICE\",\"query\":\"Talk to Gactions Integration\"}]}],\"surface\":{\"capabilities\":[{\"name\":\"actions.capability.WEB_BROWSER\"},{\"name\":\"actions.capability.AUDIO_OUTPUT\"},{\"name\":\"actions.capability.SCREEN_OUTPUT\"},{\"name\":\"actions.capability.MEDIA_RESPONSE_AUDIO\"}]},\"isInSandbox\":true,\"availableSurfaces\":[{\"capabilities\":[{\"name\":\"actions.capability.SCREEN_OUTPUT\"},{\"name\":\"actions.capability.AUDIO_OUTPUT\"}]}]}",
"curlCommand": "curl -v https://firedev.arrowai.com/integrations/goog-actions/messages/59f6b4bf8d16126f008b456a/5a619bf72c971189008b4569 -H 'Content-Type: application/json;charset=UTF-8' -H 'Google-Actions-API-Version: 2' -H 'Authorization: eyJhbGciOiJSUzI1NiIsImtpZCI6IjI2YzAxOGIyMzNmZTJlZWY0N2ZlZGJiZGQ5Mzk4MTcwZmM5YjI5ZDgifQ.eyJhdWQiOiJnYWN0aW9ucy1hcnJvd2FpLWludGVncmF0ZSIsImF6cCI6IjQ2NDA5MDk1NDc2Ny0xOWl2bnUxdjFwYXFpdWdodDJqYXJwcTJwaGtmNGRyMS5hcHBzLmdvb2dsZXVzZXJjb250ZW50LmNvbSIsImV4cCI6MTUxNzQ2NTc0OSwiaXNzIjoiaHR0cHM6Ly9hY2NvdW50cy5nb29nbGUuY29tIiwianRpIjoiZTgxNzlmN2FkZGYwYWZmYjYwNzk0MDg5MzIyN2E0MWU1NDZkZWMyOCIsImlhdCI6MTUxNzQ2NTYyOSwibmJmIjoxNTE3NDY1MzI5fQ.rmUxBhIirV0UnZvTLYYw4AtRQfNDF-3O6CaoXxD2BDZSufgfKFHz7aIUgJzUillBm4zOLFiV6SnXndIoYCG6JK60YK5tHLpqbV-P3C-5U3N05RuY7hpj1Q_B027bgUv-p7QWlg-7DmPkROmN3b3a_FsUeWqTxx5Bu5M551k_CpKvSSBzPMEB2Cw9TzGkiY9avYrISTLLxWl2JE7qKAT6P0zBbE6cdO04CxGddGNmEPkckRICsdSJ5j_wmjy3I-ItAgx3dKoDfFLW6gCI4y5MFsGFJY6cFc2e01nodslf9GlQzAhR_a4aHRRIDl47HT_b9aKpyULV3kiRR41mUkyYZw' -A 'Mozilla/5.0 (compatible; Google-Cloud-Functions/2.1; +http://www.google.com/bot.html)' -X POST -d '{\"user\":{\"userId\":\"ABwppHHHw9N9TYh-scJ5GhZtmpfFcQU2xbQBAgW1qhdllI45fimQ5QKFEVRfs2iMm6uCDJIQMApo1UZLmmnif8wqlNARnsVH744\",\"locale\":\"en-US\",\"lastSeen\":\"2018-02-01T06:04:59Z\"},\"conversation\":{\"conversationId\":\"1517465629416\",\"type\":\"NEW\"},\"inputs\":[{\"intent\":\"actions.intent.MAIN\",\"rawInputs\":[{\"inputType\":\"VOICE\",\"query\":\"Talk to Gactions Integration\"}]}],\"surface\":{\"capabilities\":[{\"name\":\"actions.capability.WEB_BROWSER\"},{\"name\":\"actions.capability.AUDIO_OUTPUT\"},{\"name\":\"actions.capability.SCREEN_OUTPUT\"},{\"name\":\"actions.capability.MEDIA_RESPONSE_AUDIO\"}]},\"isInSandbox\":true,\"availableSurfaces\":[{\"capabilities\":[{\"name\":\"actions.capability.SCREEN_OUTPUT\"},{\"name\":\"actions.capability.AUDIO_OUTPUT\"}]}]}'"
},
"sharedDebugInfo": [
{
"name": "ResponseValidation",
"subDebugEntry": [
{
"debugInfo": "API Version 2: Failed to parse JSON response string with 'INVALID_ARGUMENT' error: \": Cannot find field.\".",
"name": "UnparseableJsonResponse"
}
]
}
]
},
"response": "Gactions integration isn't responding right now. Try again soon.",
"visualResponse": {
"visualElements": []
}
}
This the agentToAssistantDebug object:
{
"conversationToken": "{\"state\":null,\"data\":{}}",
"expectUserResponse": true,
"expectedInputs": [
{
"inputPrompt": {
"noInputPrompts": [],
"richInitialPrompt": {
"items": [
{
"simpleResponse": {
"textToSpeech": "You're now talking to GActions Integration",
"displayText": "You're now talking to GActions Integration"
}
},
{
"basicCard": {
"buttons": [
{
"title": "Some Reddit to chill",
"openUrlAction": {
"url": "https://www.reddit.com"
}
}
],
"formattedText": "Here's some simp-wave to relax and chill out to",
"image": {
"url": "http://tracks.arte.tv/sites/default/files/styles/jscrop_1007x566/public/c_simpsons_2.jpg?itok=INzKpsvK",
"accessibilityText": "A World of Simpsonwave"
},
"title": "A World of Simpsonwave",
"imageDisplayOptions": "CROPPED"
}
}
],
"suggestions": []
}
},
"possibleIntents": [
{
"intent": "actions.intent.TEXT"
}
]
}
],
"resetUserStorage": false,
"userStorage": "{}",
"finalResponse": null,
"isInSandbox": true,
"customPushMessage": null,
"speech": "You're now talking to GActions Integration. ",
"displayText": "You're now talking to GActions Integration. "
}
Additionally, this is the JSON response that is being generated:
{
"conversationToken": "{\"state\":null,\"data\":{}}",
"expectUserResponse": true,
"expectedInputs": [
{
"inputPrompt": {
"noInputPrompts": [],
"richInitialPrompt": {
"items": [
{
"simpleResponse": {
"textToSpeech": "You're now talking to GActions Integration",
"displayText": "You're now talking to GActions Integration"
}
},
{
"basicCard": {
"buttons": [
{
"title": "Some Reddit to chill",
"openUrlAction": {
"url": "https://www.reddit.com"
}
}
],
"formattedText": "Here's some simp-wave to relax and chill out to",
"image": {
"url": "http://tracks.arte.tv/sites/default/files/styles/jscrop_1007x566/public/c_simpsons_2.jpg?itok=INzKpsvK",
"accessibilityText": "A World of Simpsonwave"
},
"title": "A World of Simpsonwave",
"imageDisplayOptions": "CROPPED"
}
}
],
"suggestions": []
}
},
"possibleIntents": [
{
"intent": "actions.intent.TEXT"
}
]
}
],
"resetUserStorage": false,
"userStorage": "{}",
"finalResponse": null,
"isInSandbox": true,
"customPushMessage": null,
"speech": "You're now talking to GActions Integration. ",
"displayText": "You're now talking to GActions Integration. "
}
The issue seems to be related with your response JSON. As you can see in the documentation regarding the response JSON.
"speech": "You're now talking to GActions Integration. ",
"displayText": "You're now talking to GActions Integration. "
The above are not valid parameters. Instead your response JSON should look like:
{
"conversationToken": "{\"state\":null,\"data\":{}}",
"expectUserResponse": true,
"expectedInputs": [
{
"inputPrompt": {
"noInputPrompts": [],
"richInitialPrompt": {
"items": [
{
"simpleResponse": {
"textToSpeech": "You're now talking to GActions Integration",
"displayText": "You're now talking to GActions Integration"
}
},
{
"basicCard": {
"buttons": [
{
"title": "Some Reddit to chill",
"openUrlAction": {
"url": "https://www.reddit.com"
}
}
],
"formattedText": "Here's some simp-wave to relax and chill out to",
"image": {
"url": "http://tracks.arte.tv/sites/default/files/styles/jscrop_1007x566/public/c_simpsons_2.jpg?itok=INzKpsvK",
"accessibilityText": "A World of Simpsonwave"
},
"title": "A World of Simpsonwave",
"imageDisplayOptions": "CROPPED"
}
}
],
"suggestions": []
}
},
"possibleIntents": [
{
"intent": "actions.intent.TEXT"
}
]
}
],
"resetUserStorage": false,
"userStorage": "{}",
"finalResponse": null,
"isInSandbox": true,
"customPushMessage": null
}
Edit if you use the nodejs sdk check if the response from the google sdk function is correct json and if your server answer with correct json. maybe its change the format etc?
Try it with an action.json style like the first. And the more important question how is your response to the request looking? try that json in the style the last code below creates
{
"locale": "en",
"actions": [
{
"name": "text",
"intent": {
"name": "actions.intent.TEXT",
"trigger": {
"queryPatterns": [
"some text"
]
}
},
"fulfillment": {
"conversationName": "conv name"
}
},
{
"description": "Default Welcome Intent",
"name": "MAIN",
"fulfillment": {
"conversationName": "conv name"
},
"intent": {
"name": "actions.intent.MAIN",
"trigger": {
"queryPatterns": [
"open my test app",
"open hi fish"
]
}
}
}
],
"types": [],
"conversations": {
"conv name": {
"name": "conv name",
"url": "https://yourendpoint.com/something",
"fulfillmentApiVersion": 2,
"in_dialog_intents": [
{
"name": "actions.intent.NO_INPUT"
},
]
}
}
}
this here is a function that create an valid response:
/**
message = string
slots = array
state = object
**/
function answerWithMessage(message,slots,state){
let display = message.replace(/<[^>]*>/g, '');
let voicemessage = message.toLowerCase();
let jsonResponse = {
conversationToken: JSON.stringify(state),
expectUserResponse: true,
expectedInputs: [
{
inputPrompt: {
richInitialPrompt: {
items: [
{
simpleResponse: {
ssml: voicemessage,
displayText: display,
},
}
],
}
},
possibleIntents: [
{
intent: "actions.intent.TEXT"
}
],
speechBiasingHints: slots
}
]
};
return JSON.stringify(jsonResponse,null, 4);
}
And here is a repro with example google actions sdk: https://github.com/haukedau/googleActionsInit but the answer there is not completly correct but it will do the work as well above response message style is better.
Hi I think your issue is just you call an object
"inputPrompt": {
and an array but both are in the same position look in the explanation below.
"noInputPrompts": [],
https://developers.google.com/actions/assistant/helpers#calling_the_helper_1
I hope I could help you.
Best regards
Patrick

Nested json as a request body Input using swagger-ui in node js

I am new to node js and swagger-ui.
I want to pass below input body to my web service using swagger-ui,
I am able to pass normal json like:
{
"username":"abc",
"password":"******"
}
but I want to give following input to my web service using swagger-ui.
{
"data":
{"username":"abc",
"password":"******"
}
}
my api-docs.json file is below:
{
"info": {
"title": "Node Swagger API",
"version": "1.0.0",
"description": "Demonstrating how to describe a RESTful API with Swagger"
},
"host": "localhost:5002",
"basePath": "/",
"swagger": "2.0",
"paths": {
"/login": {
"post": {
"description": "user login",
"produces": [
"application/json"
],
"parameters": [
{
"name": "userName",
"description": "username to get userType",
"required": true,
"type": "string",
"in": "formData"
},
{
"name": "password",
"description": "password to get userType",
"required": true,
"type": "string",
"in": "formData"
}
],
"responses": {
"0": {
"description": "Access token has been expired. Please login again."
},
"200": {
"description": "Successfully returns the response"
},
"400": {
"description": "Invalid input Parameters"
},
"401": {
"description": "Invalid Access Token"
},
"404": {
"description": "No data found"
},
"500": {
"description": "Internal Server Error"
}
}
}
}
},
"definitions": {},
"responses": {},
"parameters": {},
"securityDefinitions": {},
"tags": []
}
So How can pass below input using swagger-ui to my web service:
{
"data":
{"username":"abc",
"password":"******"
}
}
Any Help will be appreciable.
Thanks In Advance.
I always use the yml format. Try this. should work. Now you will get the details in the req.body.
{
"info": {
"title": "Node Swagger API",
"version": "1.0.0",
"description": "Demonstrating how to describe a RESTful API with Swagger"
},
"host": "localhost:5002",
"basePath": "/",
"swagger": "2.0",
"paths": {
"/login": {
"post": {
"description": "user login",
"produces": [
"application/json"
],
"parameters": [
{
"name": "userDetails",
"description": "username to get userType",
"required": true,
"in": "body",
"schema": {
"$ref": "#/definitions/User"
}
}
],
"responses": {
"0": {
"description": "Access token has been expired. Please login again."
},
"200": {
"description": "Successfully returns the response"
},
"400": {
"description": "Invalid input Parameters"
},
"401": {
"description": "Invalid Access Token"
},
"404": {
"description": "No data found"
},
"500": {
"description": "Internal Server Error"
}
}
}
}
},
"definitions": {
"User" : {
"type":"object",
"properties": {
"data": {
"type": "object",
"properties": {
"username": {
"type": "string"
},
"password": {
"type": "string"
}
}
}
}
}
},
"responses": {},
"parameters": {},
"securityDefinitions": {},
"tags": []
}

Problems with v1/queryContext needed for SpagoBI integration

In version 1.7.0 of Orion CB running the docker version in Docker for Windows,
if I create a simple object doing POST http://localhost:1026/v1/updateContext
with the body:
{
"contextElements": [
{
"type": "Car",
"id": "myNewCar",
"attributes": [
{
"name": "maxSpeed",
"type": "integer",
"value": "220"
}
]
}
],
"updateAction": "APPEND"
}
I get the answer:
{
"contextResponses": [
{
"contextElement": {
"type": "Car",
"isPattern": "false",
"id": "myNewCar",
"attributes": [
{
"name": "maxSpeed",
"type": "integer",
"value": ""
}
]
},
"statusCode": {
"code": "200",
"reasonPhrase": "OK"
}
}
]
}
Then, if I do POST http://localhost:1026/v1/queryContext with the same headers and the same components with the body
{
"entities": [
{
"type": "Car",
"isPattern": "false",
"id": "myNewCar"
}
]
}
I get the following:
{
"errorCode": {
"code": "404",
"reasonPhrase": "No context element found"
}
}
Which shouldn't be problematic (I can query the entities with v2 API, for instance) if it wasn't needed for integration with data representation tools such as SpagoBI as documented in http://spagobi.readthedocs.io/en/latest/user/NGSI/README/
What can I do? I am doing something wrong with the context provision?
Thanks!
My problem was that I was using a imported Postman collection of the API (Downloaded from https://github.com/telefonicaid/fiware-orion/tree/develop/doc/apiary/v2) and accidentally I was using the header Fiware-Service.
You are right and your tests work properly.
Thanks for the prompt reply!!

Orion JSON Bad Request

I'm currently trying to subscribe Orion and Cosmos. All data sent to Orion is being updated without any issue. But, when posting to http://xxx.xxx.xx.xx:1026/v1/subscribeContext I'm getting the following error:
{
"subscribeError": {
"errorCode": {
"code": "400",
"reasonPhrase": "Bad Request",
"details": "JSON Parse Error"
}
}
}
This is the json string I'm sending:
{
"entities": [
{
"type": "Location",
"isPattern": "false",
"id": "Device-1"
}
],
"reference": "http://52.31.144.170:5050/notify",
"duration": "PT10S",
"notifyConditions": [
{
"type": "ONCHANGE",
"condValues": [
"position"
]
}
],
"attributes": [
"position"
]
}
The entity updating OK in Orion is:
{
"type": "Location",
"isPattern": "false",
"id": "Device-1",
"attributes": [
{
"name": "position",
"type": "coords",
"value": "24,21",
"metadatas": [
{
"name": "location",
"type": "string",
"value": "WGS84"
}
]
},
{
"name": "id",
"type": "device",
"value": "1"
}
]
}
I've tried with many different examples from readthedocs, and other responses in StackOverflow unsuccessfully.
Which is the correct format? Should I call /subscribeContext before or after updating Orion with /contextEntities?
Orion Context Broker version is 0.26.1.
Thank you in advance.
Taking into account that the same payload works ok when send using curl (see this execution session) I tend to think that some issue in the client (maybe hiden by a programming framework?) is causing the problem.